繁体   English   中英

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

[英]Running an external program from python: piping without waiting for all output

我看过在Python调用外部命令的情况,并尝试了子进程和os.popen的所有可能方式,但似乎没有任何效果。

如果我尝试

import os
stream = os.popen("program.ex -f file.dat | grep fish | head -4")

我得到线和线

grep: broken pipe

如果我切换grephead命令,它将永远不会进入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中运行(即,头和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上,可能等待所有输出完成。

您正在寻找这个令人惊叹但不知名的库:

https://github.com/kennethreitz/envoy

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

您可以使用bash处理管道。

它只能运行脚本文件,而不能运行命令( bash -e echo给出/bin/echo: /bin/echo: cannot execute binary file

bash -e <script to run>

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

从第一个过程开始,这仍然给我带来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'

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM