8

我在 Python27 中遇到了问题,close_fds所以在做了一些研究后,我发现了这个例子

from subprocess import Popen, PIPE, STDOUT
p1 = Popen(['cat'], stdin=PIPE, stdout=PIPE)
p2 = Popen(['grep', 'a'], stdin=p1.stdout, stdout=PIPE)
p1.stdin.write("aaaaaaaaaaaaaaaa\n")
p1.stdin.close()
p2.stdout.read()

我的问题是我不明白为什么p1.stdin保持开放。p1不是子级,p2因此p2不应继承任何p1资源,除非p1.stdout明确传递。close_fds=True此外,为什么设置p2可以解决问题?这里是这样写的:

如果 close_fds 为 true,则在执行子进程之前,将关闭除 0、1 和 2 之外的所有文件描述符。

因此,即使我能够理解和之间的继承,p1也不应该被关闭,因为它是标准输入 (1)。p2p1.stdinclose_fds=True

4

1 回答 1

13

由于p1p2是兄弟姐妹,因此它们的相应进程之间不会直接进行继承。

但是,考虑父级视为 的文件描述符,由其p1.stdin继承p1并重定向到其stdin. 此文件描述符存在于父进程中(具有 0、1 或 2 以外的数字 - 您可以通过打印来验证这一点p1.stdin.fileno()),并且它必须存在,因为我们打算从父进程写入它。正是这个文件描述符被无意继承并保持打开状态p2

当一个打开的文件被多个文件描述符引用时,就像 的情况一样p1.stdin,只有在所有描述符都关闭时才会关闭。这就是为什么有必要同时关闭p1.stdin 传递close_fdsp2。(如果您手动实现了生成代码,您只需在第二个之后关闭文件描述符fork()。)

于 2013-11-13T09:47:18.820 回答