Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sqlite/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从python运行外部程序:不等待所有输出的管道_Python_Bash_Shell_Python 2.7_Subprocess - Fatal编程技术网

从python运行外部程序:不等待所有输出的管道

从python运行外部程序:不等待所有输出的管道,python,bash,shell,python-2.7,subprocess,Python,Bash,Shell,Python 2.7,Subprocess,我已经研究并尝试了使用subprocess和os.popen的所有可能的方法,但似乎没有任何效果 如果我尝试 import os stream = os.popen("program.ex -f file.dat | grep fish | head -4") 我收到了一行又一行的信件 grep: broken pipe 如果我切换grep和head命令,它永远不会到达grep命令,因为program.ex的输出太长(这就是为什么我使用head-4运行的原因) 当然,由于管道的原因,以下操作

我已经研究并尝试了使用subprocess和os.popen的所有可能的方法,但似乎没有任何效果

如果我尝试

import os
stream = os.popen("program.ex -f file.dat | grep fish | head -4")
我收到了一行又一行的信件

grep: broken pipe
如果我切换
grep
head
命令,它永远不会到达grep命令,因为program.ex的输出太长(这就是为什么我使用
head-4
运行的原因)

当然,由于管道的原因,以下操作失败:

import subprocess as sp
cmd = "program.ex -f file.dat | grep fish | head -4"
proc = sp.Popen(cmd.split(),stdout=sp.PIPE,stderr=sp.PIPE)
stdout, stderr = proc.communicate()
所以我试着把它拆开

cmd1 = "program.ex -f file.ex"
cmd2 = "head -4"
cmd3 = "grep fish"
proc1 = sp.Popen(cmd1.split(),stdout=sp.PIPE,stderr=sp.PIPE)
proc2 = sp.Popen(cmd2.split(),stdout=sp.PIPE,stdin=proc1.stdout)
proc3 = sp.Popen(cmd3.split(),stdout=sp.PIPE,stdin=proc2.stdout)
stdout, stderr = proc1.communicate()
它确实会运行,只是在cmd1上卡住了,因为program.ex的输出太长了

最后,我尝试将其隐藏在一个外部shell脚本和fortran程序中,但fortran程序没有

call system("program.ex -f file.dat | grep fish | head -4")
我猜这又把python搞砸了

注意:如果我直接在终端中执行此操作,则不需要从program.ex获取整个输出,命令立即完成

所以,我的问题是:

如何让上述命令像在终端中一样在python中运行(即,head和grep program.ex的输出,而无需等待program.ex的所有输出)?

非常感谢您的帮助

编辑:

我还尝试了
shell=True

import subprocess as sp
cmd = "program.ex -f file.dat | head -4 | grep fish"
proc = sp.Popen(cmd.split(),stdout=sp.PIPE,stderr=sp.PIPE,shell=True)
stdout, stderr = proc.communicate()

虽然stderr有预期的(不需要的)内容,但stdout是空的。如果我将上面的
cmd
变量替换为调用系统命令的fortran程序的名称,那么它将再次挂起program.ex,可能等待所有输出完成。

这一令人惊讶但并不广为人知的库可能就是您要寻找的:


确保使用Github版本,而不是与
pip一起安装的版本。顺便说一下,它只是一个文件。

您可以使用bash来处理管道

它只能运行脚本文件,不会运行命令(
bash-e echo
gives
/bin/echo:/bin/echo:无法执行二进制文件

bash-e


如果将命令放在脚本文件中,它将运行它们

这仍然会在第一个进程的stderr中出现某种错误,但对于您的目的来说,它可能仍然足够好?使用多管道示例,但在输出进程上调用
.communicate()


使用
shell=True
,指向
Popen()
的命令应为单个字符串。(不幸的是,我也无法使用
shell=True
import subprocess
cmd1 = ['yes', 'fishy'] # is this similar enough to your example program?
cmd2 = ['head', '-4']
cmd3 = ['grep', 'fish']
proc1 = subprocess.Popen(cmd1, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
proc2 = subprocess.Popen(cmd2, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
                         stdin=proc1.stdout)
proc3 = subprocess.Popen(cmd3, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
                         stdin=proc2.stdout)
result, err3 = proc3.communicate()
proc2.wait()
err2 = proc2.stderr.read()
proc1.stdout.close()
proc1.wait()
err1 = proc1.stderr.read() # 'yes: standard output: Broken pipe\nyes: write error\n'