我喜欢将Python(2.6,对不起!)等效于这个shell管道:
$ longrunningprocess | sometextfilter | gzip -c
也就是说,我必须调用二进制longrunningprocess
,通过sometextfilter
过滤其输出,并需要输出gzip
。
我知道如何使用subprocess
管道,但我需要管道输出(可能使用yield
)而不是一次性完成。例如。这个
https://security.openstack.org/guidelines/dg_avoid-shell-true.html
仅适用于一次获取所有输出。
请注意,longrunningprocess
和sometextfilter
都是外部程序,不能用Python函数替换。
提前感谢任何提示或示例!
答案 0 :(得分:0)
同样,我认为这很困难,而Python(应该是)很容易。只是连接子进程才能正常工作,似乎:
def get_lines():
lrp = subprocess.Popen(["longrunningprocess"],
stdout=subprocess.PIPE,
close_fds=True)
stf = subprocess.Popen(["sometextfilter"],
stdin=lrp.stdout,
stdout=subprocess.PIPE,
bufsize=1,
close_fds=True)
for l in iter(stf.stdout.readline, ''):
yield l
lrp.stdout.close()
stf.stdout.close()
stf.stdin.close()
stf.wait()
lrp.wait()
[J.F.Sebastian所做的修改。谢谢!]
然后我可以使用Pythons gzip进行压缩。
答案 1 :(得分:0)
shell语法针对单行进行了优化,使用它:
#!/usr/bin/env python2
import sys
from subprocess import Popen, PIPE
LINE_BUFFERED = 1
ON_POSIX = 'posix' in sys.builtin_module_names
p = Popen('longrunningprocess | sometextfilter', shell=True,
stdout=PIPE, bufsize=LINE_BUFFERED, close_fds=ON_POSIX)
with p.stdout:
for line in iter(p.stdout.readline, ''):
print line, # do something with the line
p.wait()
如果您想手动模拟管道:
#!/usr/bin/env python2
import sys
from subprocess import Popen, PIPE
LINE_BUFFERED = 1
ON_POSIX = 'posix' in sys.builtin_module_names
sometextfilter = Popen('sometextfilter', stdin=PIPE, stdout=PIPE,
bufsize=LINE_BUFFERED, close_fds=ON_POSIX)
longrunningprocess = Popen('longrunningprocess', stdout=sometextfilter.stdin,
close_fds=ON_POSIX)
with sometextfilter.stdin, sometextfilter.stdout as pipe:
for line in iter(pipe.readline, ''):
print line, # do something with the line
sometextfilter.wait()
longrunningprocess.wait()