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

我有以下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 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()
。这将为您提供一对连接的真实文件描述符(而不是Python
file
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的源代码之后产生的。