我注意到在Python3子进程中,Popen参数close_fds
的默认值从False
更改为True
,我想知道是什么原因以及几乎总是将close_fds
设置为True
(因为我仍在使用Python 2.7)是否是一个好习惯。
我找到了一个显示close_fds=False
问题的链接。
https://bugs.python.org/issue7213
不幸的是,我不清楚为什么会这样。
import subprocess as sub
p1 = sub.Popen(['cat'], stdin=sub.PIPE, stdout=sub.PIPE, close_fds=False)
p2 = sub.Popen(['grep', 'a'], stdin=p1.stdout, stdout=sub.PIPE, close_fds=False)
p1.stdin.write("aaaaaaaaaaaaaaaa\n")
p1.stdin.close()
p2.stdout.read() # Hangs on Python 2
该程序挂起在Python2上,不在Python3上,如果close_fds
设置为True
,则根本不挂起。所以我想知道......那里的实际问题是什么?
编辑:它挂在我的Python 2.6上,并停止挂在2.7上
那里的实际问题是什么?
在Python 2.6中,p1.stdin
管道写入端的文件句柄由p2
继承,它不关心或不了解它,因此保持打开状态。因此,虽然父进程执行p1.stdin.close()
,但写入管道保持打开,因此cat
不会在其输入上检测到EOF并继续等待来自管道的数据,从而阻塞整个流程链。
使用fcntl(…, F_SETFD, FD_CLOEXEC)
的Python 2.7调用跟随stdin
和stdout
管道的创建,因此写管道端不会被p2
继承并且被p1.stdin.close()
有效关闭。