Python2.x subprocess.Popen 的 Broken pipe 解决方法
#!/usr/bin/env python
p1 = Popen(["cat", "somebigfile"], stdout = PIPE)
p2 = Popen(["head"], stdin = p1.stdout, stdout = PIPE)
print p2.communicate()[0]
会出现
cat: write error: Broken pipe
原因是在Unix-like系统中,Python启动就会SIG_IGN掉SIG_PIPE,致使cat获取不了SIG_PIPE信号,还向已关闭的管道写入。很久之前就有人提出这个BUG了,这个BUG在Python 3.x已经修复,但是一直没有在Python 2.x实现。
解决方法如下:
1. 下载对应版本的Python源码,找到Lib\subprocess.py(我发现2.6.x的跟2.7.x的就不同)
2. 把该文件放到项目文件夹,改名为sub.py
3. 作如下改动:
--- /usr/lib/python2.6/subprocess.py 2010-04-16 21:58:41.000000000 +0800
+++ sub.py 2011-08-26 17:45:57.576284992 +0800
@@ -429,7 +429,7 @@
import fcntl
import pickle
-__all__ = ["Popen", "PIPE", "STDOUT", "call", "check_call", "CalledProcessError"]
+__all__ = ["Popen", "PIPE", "STDOUT", "call", "check_call", "CalledProcessError", "_eintr_retry_call"]
try:
MAXFD = os.sysconf("SC_OPEN_MAX")
4. 新建new_subprocess.py, 建立Popen_new类,继承原来subprocess的Popen,并把sub.py里面Popen类的POSIX版本的_execute_child方法copy过来。
5. 在
if cwd is not None:
os.chdir(cwd)
后面加上如下代码:
import signal
signals = ('SIGPIPE', 'SIGXFZ', 'SIGXFSZ')
for sig in signals:
if hasattr(signal, sig):
signal.signal(getattr(signal, sig), signal.SIG_DFL)
(此处有一个示例,Python 2.6.5版本的)
6. 在项目里
from new_subprocess import Popen_new as Popen
即可
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。