【问题标题】:Using file descriptors to communicate between processes使用文件描述符在进程之间进行通信
【发布时间】:2010-09-22 12:11:56
【问题描述】:

我有以下 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)

我怎样才能重写它,使它不会使用Popencat?我需要一种方法从在交互式 shell 中运行的 shell 函数传递数据,该方法不会与其他函数创建的数据混合(因此我不能使用 stdout 或 stderr)。

【问题讨论】:

  • 为什么不能直接subprocess.Popen()shell?
  • @llasram 因为我需要一个交互式 shell 来捕获传递给完成内置 compadd 的参数。没有 tty - 没有交互 - 没有完成。
  • 我不太了解...你能提供一个具体的例子吗?
  • @llasram 什么例子?如果我有一个交互式 shell,我可以使用 tab 来完成。当我按下 tab zsh 调用一些能够找到建议的 shell 函数。这些函数使用 compadd 内置函数将找到的建议传递给 zsh 补全系统。但是有一些问题: 1、zsh在没有连接到tty时拒绝交互。 2. 完成函数可能会向 stderr 回显某些内容,而 zsh 本身会向 stdout 回显。在这段代码中捕获compadd 参数,我可以定义compadd 函数,将它们通过管道传递给给定的FD,然后使用os.write(child_fd, "echo /\t")

标签: python ipc zsh file-descriptor


【解决方案1】:

好的,我想我现在已经解决了你的问题,看看你可以采取两种不同的方法。

如果您绝对想为子进程中的 shell 提供已经打开的文件描述符,那么您可以将 catPopen() 替换为对 os.pipe() 的调用。这将为您提供一对连接的真实文件描述符(不是 Python file 对象)。写入第二个文件描述符的任何内容都可以从第一个文件描述符中读取,替换您的陪审团操纵的cat-pipe。 (虽然“猫管”说起来很有趣……)。如果您需要双向对,也可以使用套接字对 (socket.socketpair()) 来达到相同的目的。

或者,您可以使用命名管道(又名 FIFO)进一步简化您的生活。如果您不熟悉该工具,命名管道是位于文件系统命名空间中的单向管道。 os.mkfifo() 函数将在文件系统上创建管道。然后,您可以打开管道以在您的主进程中读取,并打开它以从您的 shell 子进程写入/直接输出到它。这应该会简化您的代码并打开使用现有库(如 Pexpect)与 shell 交互的选项。

【讨论】:

  • 谢谢,我没有使用mkfifo,因为它会创建新文件。我尝试使用os.pipe(),但没有猜到我应该在子脚本中使用第二个 fd,在父脚本中使用第一个。使用pty.fork的想法是在检查了pexpect的源代码之后产生的。
猜你喜欢
  • 2020-09-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-29
  • 2012-01-18
  • 2012-06-19
  • 2023-03-07
  • 1970-01-01
相关资源
最近更新 更多