感谢以下有用的建议:
所以我似乎已经修好了
-
单独命令到Popen的单独调用
-
stderr = subprocess.PIPE作为每个Popen链的参数 .
新代码:
import subprocess
import shlex
import logging
def run_shell_commands(cmds):
""" Run commands and return output from last call to subprocess.Popen.
For usage see the test below.
"""
# split the commands
cmds = cmds.split("|")
cmds = list(map(shlex.split,cmds))
logging.info('%s' % (cmds,))
# run the commands
stdout_old = None
stderr_old = None
p = []
for cmd in cmds:
logging.info('%s' % (cmd,))
p.append(subprocess.Popen(cmd,stdin=stdout_old,stdout=subprocess.PIPE,stderr=subprocess.PIPE))
stdout_old = p[-1].stdout
stderr_old = p[-1].stderr
return p[-1]
pattern = '"^85567 "'
file = "j"
cmd1 = 'grep %s %s | sort -g -k3 | head -10 | cut -d" " -f2,3' % (pattern, file)
p = run_shell_commands(cmd1)
out = p.communicate()
print(out)
原帖:
我花了太长时间试图解决一个简单的子进程问题.Popen .
码:
import subprocess
cmd = 'cat file | sort -g -k3 | head -20 | cut -f2,3' % (pattern,file)
p = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE)
for line in p.stdout:
print(line.decode().strip())
文件输出~1000行的长度:
...
sort: write failed: standard output: Broken pipe
sort: write error
文件输出> 241行的长度:
...
sort: fflush failed: standard output: Broken pipe
sort: write error
文件输出<241行的长度很好 .
我一直在阅读文档和谷歌搜索疯狂,但有一些基本的东西模块,我缺少...也许与缓冲区 . 我尝试过p.stdout.flush()并使用缓冲区大小和p.wait() . 我试图用'睡眠20;等命令重现这一点; cat moderatefile'但这似乎运行没有错误 .
5 回答
从subprocess docs上的食谱:
这是因为你不应该在传递给
subprocess.Popen
的命令中使用"shell pipes",你应该像这样使用subprocess.PIPE
:但我不得不说你想要做的事情可以在纯python中完成,而不是调用一堆shell命令 .
我一直有同样的错误 . 甚至把管道放在一个bash脚本中并执行它而不是Python中的管道 . 从Python它将得到破坏的管道错误,从bash它不会 .
在我看来,也许在头部之前的最后一个命令抛出错误,因为它的(排序)STDOUT被关闭 . Python必须接受这一点,而对于shell,错误是沉默的 . 我已经改变了我的代码以消耗整个输入并且错误消失了 .
因为管道可能会在磁头退出之前缓冲整个输出,因此使用较小的文件也是有意义的 . 这可以解释较大文件的中断 .
例如,而不是'头-1'(在我的情况下,我只想要第一行),我做了一个awk'NR == 1'
根据管道中出现'head -X'的位置,可能有更好的方法 .
你不需要
shell=True
. 不要调用shell . 我就是这样做的:使用它后看看你是否遇到缓冲区的问题?
尝试使用communicate(),而不是直接从stdout读取 .
python文档说这个:
http://docs.python.org/library/subprocess.html#subprocess.Popen.stdout