我在Python27中遇到了close_fds
的问题,所以在做了一些研究后我发现了example:
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
可以解决问题? Here写成:
如果close_fds为true,则在执行子进程之前将关闭除0,1和2之外的所有文件描述符。
所以,即使我能够理解p1
和p2
之间的继承仍然p1.stdin
不应该由close_fds=True
关闭,因为它是标准输入( 1)。
答案 0 :(得分:11)
由于p1
和p2
是兄弟姐妹,因此不会直接在相应的进程之间进行继承。
但是,请考虑父级视为p1.stdin
的文件描述符,由p1
继承并重定向到其stdin
。此文件描述符存在于父进程中(使用0,1或2之外的数字 - 您可以通过打印p1.stdin.fileno()
来验证这一点),并且它必须存在,因为我们打算从父进程写入它。这个文件描述符无意中被p2
继承并保持打开状态。
当多个文件描述符引用打开的文件时(如p1.stdin
的情况),只有在所有关闭描述符时才会关闭它。这就是为什么有必要关闭p1.stdin
和将close_fds
传递给p2
。 (如果您手动实现了产生代码,则只需在第二个fork()
之后关闭文件描述符。)