我查看过Calling an external command in Python并尝试使用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中运行(即,从program.ex输出并grep输出而无需等待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上,可能等待所有输出完成。
答案 0 :(得分:0)
这个令人惊叹但却不为人知的图书馆可能正是您所寻找的:
https://github.com/kennethreitz/envoy
请务必使用Github版本,而不是使用pip
安装的版本。顺便说一句,它只是一个文件。
答案 1 :(得分:0)
您可以使用bash来处理管道。
它只能运行脚本文件而且不会运行命令(bash -e echo
给出/bin/echo: /bin/echo: cannot execute binary file
)
bash -e <script to run>
如果您将命令放在脚本文件中,它将运行它们
答案 2 :(得分:0)
这仍然让我在第一个进程中出现了stderr中的错误,但是它仍然可以用于你的目的吗?使用多个管道示例,但在输出进程上调用.communicate()
:
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'