Python 使用文件描述符在进程之间进行通信
我有以下python代码:Python 使用文件描述符在进程之间进行通信,python,ipc,zsh,file-descriptor,Python,Ipc,Zsh,File Descriptor,我有以下python代码: import pty import subprocess os=subprocess.os from subprocess import PIPE import time import resource pipe=subprocess.Popen(["cat"], stdin=PIPE, stdout=PIPE, stderr=PIPE, \ close_fds=True) skip=[f.fileno() for f i
import pty
import subprocess
os=subprocess.os
from subprocess import PIPE
import time
import resource
pipe=subprocess.Popen(["cat"], stdin=PIPE, stdout=PIPE, stderr=PIPE, \
close_fds=True)
skip=[f.fileno() for f in (pipe.stdin, pipe.stdout, pipe.stderr)]
pid, child_fd = pty.fork()
if(pid==0):
max_fd=resource.getrlimit(resource.RLIMIT_NOFILE)[0]
fd=3
while fd<max_fd:
if(fd not in skip):
try:
os.close(fd)
except OSError:
pass
fd+=1
enviroment=os.environ.copy()
enviroment.update({"FD": str(pipe.stdin.fileno())})
os.execvpe("zsh", ["-i", "-s"], enviroment)
else:
os.write(child_fd, "echo a >&$FD\n")
time.sleep(1)
print pipe.stdout.read(2)
导入pty
导入子流程
os=子流程.os
从子流程导入管道
导入时间
导入资源
管道=子流程.Popen([“cat”],标准输入=管道,标准输出=管道,标准输出=管道\
关闭(fds=真)
skip=[f.fileno()表示f-in(pipe.stdin、pipe.stdout、pipe.stderr)]
pid,child_fd=pty.fork()
如果(pid==0):
max_fd=resource.getrlimit(resource.RLIMIT_NOFILE)[0]
fd=3
虽然fd好,但我想我现在已经掌握了你的问题,并且看到了你可以采取的两种不同方法
如果您绝对希望为子进程中的shell提供一个已经打开的文件描述符,那么您可以用调用os.pipe()
来替换cat
的Popen()
。这将为您提供一对连接的真实文件描述符(而不是Pythonfile
objects)。写入第二个文件描述符的任何内容都可以从第一个文件描述符读取,从而替换您的陪审团操纵的cat
-pipe。(虽然说“猫管”很有趣…)。如果需要双向套接字对,也可以使用套接字对(socket.socketpair()
)来实现相同的目的
或者,您可以通过使用命名管道(又名FIFO)进一步简化您的生活。如果您不熟悉该工具,那么命名管道是位于文件系统名称空间中的单向管道。os.mkfifo()
函数将在文件系统上创建管道。然后可以在主进程中打开管道进行读取,并从shell子进程中打开管道进行写入/直接输出。这将简化您的代码并打开使用现有库与shell交互的选项。为什么您不能直接subprocess.Popen()
shell?@llasram,因为我需要一个交互式shell来捕获传递给Compald的参数。没有tty-没有互动-没有完成。我不太明白。。。你能提供一个具体的例子吗?@llasram什么例子?如果我有一个交互式shell,我可以使用tab来完成。当我按下tab键时,zsh调用一些能够找到建议的shell函数。这些函数使用compadd
内置函数将找到的建议传递给zsh完成系统。但也存在一些问题:1。zsh在未连接到tty时拒绝交互。2.完成函数可能会向stderr回显某些内容,而zsh本身也会向stdout回显。在这段代码中,为了捕获compadd
参数,我可以定义compadd
函数,使其通过管道传输到给定的FD,然后使用os.write(child\u FD,“echo/\t”)
。谢谢,我没有使用mkfifo
,因为它会创建新文件。我尝试使用os.pipe()
,但猜不出应该在子脚本中使用第二个fd,在父脚本中使用第一个fd。使用pty.fork
的想法是在检查了pexpect的源代码之后产生的。