“标准”子进程管道技术(例如 http://docs.python.org/2/library/subprocess.html#replacing-shell-pipeline )可以“升级”为两个管道吗?
# How about
p1 = Popen(["cmd1"], stdout=PIPE, stderr=PIPE)
p2 = Popen(["cmd2"], stdin=p1.stdout)
p3 = Popen(["cmd3"], stdin=p1.stderr)
p1.stdout.close() # Allow p1 to receive a SIGPIPE if p2 exits.
p1.stderr.close()
#p2.communicate() # or p3.communicate()?
好吧,这实际上是一个不同的用例,但最接近的起点似乎是管道示例。顺便问一下,“正常”管道中的 p2.communicate() 如何驱动 p1?这是正常的管道供引用:
# From Python docs
output=`dmesg | grep hda`
# becomes
p1 = Popen(["dmesg"], stdout=PIPE)
p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)
p1.stdout.close() # Allow p1 to receive a SIGPIPE if p2 exits.
output = p2.communicate()[0]
我想我最终对communicate()
支持什么样的“流程图”(或者可能只是树?)感兴趣,但我们将把一般情况留到另一天。
更新:这是基准功能。如果不使用communicate(),则创建2个从p1.stdout和p2.stdout读取的线程。在主进程中,通过 p1.stdin.write() 注入(inject)输入。问题是我们是否可以仅使用 communications() 来驱动 1-source、2-sink 图
最佳答案
您可以使用 bash 的 process substitution :
from subprocess import check_call
check_call("cmd1 > >(cmd2) 2> >(cmd3)", shell=True, executable="/bin/bash")
它将 cmd1
的 stdout 重定向到 cmd2
,将 cmd1
的 stderr 重定向到 cmd3
。
如果您不想使用bash
,那么您问题中的代码应该按原样工作,例如:
#!/usr/bin/env python
import sys
from subprocess import Popen, PIPE
from textwrap import dedent
# generate some output on stdout/stderr
source = Popen([sys.executable, "-c", dedent("""
from __future__ import print_function
import sys
from itertools import cycle
from string import ascii_lowercase
for i, c in enumerate(cycle(ascii_lowercase)):
print(c)
print(i, file=sys.stderr)
""")], stdout=PIPE, stderr=PIPE)
# convert input to upper case
sink = Popen([sys.executable, "-c", dedent("""
import sys
for line in sys.stdin:
sys.stdout.write(line.upper())
""")], stdin=source.stdout)
source.stdout.close() # allow source to receive SIGPIPE if sink exits
# square input
sink_stderr = Popen([sys.executable, "-c", dedent("""
import sys
for line in sys.stdin:
print(int(line)**2)
""")], stdin=source.stderr)
source.stderr.close() # allow source to receive SIGPIPE if sink_stderr exits
sink.communicate()
sink_stderr.communicate()
source.wait()
关于python - "3-way"Python 子进程管道 : send stdout and stderr to two different processes?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19593456/