从shell运行以下命令:yes | head -1
,输出y
。使用python的子进程模块用shell调用它无限期地挂起:
import subprocess
arg = "yes | head -1"
process = subprocess.Popen(arg,
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
print "Command started: %d" % process.pid
r = process.communicate()
print "Command ended: %s %s" % r
使用kill
外部杀死该过程无济于事,也不会让孩子使用preexec_fn=os.setsid
来处理会话负责人。
可能导致这种行为的原因是什么,无论如何我可以阻止它?
我正在运行python 2.7.3而我的/bin/sh
是GNU bash, version 3.2.48(1)-release (x86_64-apple-darwin12)
答案 0 :(得分:0)
事实证明,这是由于python未知在subprocess
模块中的exec之前重置信号处理程序的已知问题引起的。
这是导致'yes' reporting error with subprocess communicate()的问题,除了GNU yes
之外,写入返回的EPIPE导致程序中止,而使用BSD yes
(用于据我所知OS X而言,未检查写入的返回码,因此如果没有SIGPIPE
,yes
将不会终止。
可以通过向后移植reset_signals
代码来解决此问题,如上面链接的问题:
def restore_signals():
signals = ('SIGPIPE', 'SIGXFZ', 'SIGXFSZ')
for sig in signals:
if hasattr(signal, sig):
signal.signal(getattr(signal, sig), signal.SIG_DFL)
然后在preexec_fn=restore_signals
来电中设置Popen
。