新手python子进程:“写入错误:断开的管道”
感谢以下有用的建议:
所以它似乎是固定的,当我
新代码:
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; 猫中等文件“,但这似乎运行没有错误。
从子流程文档的配方:
# To replace shell pipeline like output=`dmesg | grep hda`
p1 = Popen(["dmesg"], stdout=PIPE)
p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)
output = p2.communicate()[0]
这是因为你不应该在传递给subprocess.Popen
的命令中使用“shell管道”,你应该像这样使用subprocess.PIPE
:
from subprocess import Popen, PIPE
p1 = Popen('cat file', stdout=PIPE)
p2 = Popen('sort -g -k 3', stdin=p1.stdout, stdout=PIPE)
p3 = Popen('head -20', stdin=p2.stdout, stdout=PIPE)
p4 = Popen('cut -f2,3', stdin=p3.stdout)
final_output = p4.stdout.read()
但是我不得不说,你正在试图做的事情可以用纯Python来完成,而不是调用一堆shell命令。
我一直有同样的错误。 甚至把管道放在一个bash脚本中,并执行它,而不是Python中的管道。 从Python它会得到损坏的管道错误,从bash它不会。
在我看来,也许在头部之前的最后一个命令会抛出一个错误,因为它的(排序)STDOUT是关闭的。 Python必须在这方面采取行动,而在shell中,错误是无声的。 我更改了我的代码以消耗整个输入,并且错误消失了。
对于较小的文件也是有意义的,因为管道可能在磁头退出前缓冲整个输出。 这将解释更大的文件的休息。
例如,而不是'head -1'(在我的情况下,我只想要第一行),我做了一个awk'NR == 1'
根据管道中'head -X'的位置,可能有更好的方法。
链接地址: http://www.djcxy.com/p/13475.html