将子进程的标准输出重定向到 2 个或更多子进程的标准输入
Posted
技术标签:
【中文标题】将子进程的标准输出重定向到 2 个或更多子进程的标准输入【英文标题】:Redirect stdout of a subprocess to stdin of 2 or more subprocesses 【发布时间】:2015-01-02 10:30:01 【问题描述】:基本上我想学习如何使用stdout
的一个subprocess
(比如proc1
)作为stdin
的2 个或更多其他subprocess
es(比如proc2
和proc3
)蟒蛇。
嗨,
我需要 zcat
一个 .gz 文件并将发送到 subprocess.PIPE
的输出用于 cksum
(unix 实用程序)和行数。
我可以像这样在 bash 中做到这一点......
[hashroot@dev_server 12]$ zcat ABC_C_TPM_26122014.data.gz | tee >(wc -l) >(cksum)| tail -2
2020090579 112180
586
我想在 python 中做同样的事情。
只要我这样做......
>>> import subprocess
>>> import os
>>> fl123 = 'ABC_C_TPM_26122014.data.gz'
>>> pqr123 = subprocess.Popen(['zcat', fl123], stdout=subprocess.PIPE)
>>> subprocess.check_output(['cksum'], stdin=pqr123.stdout)
b'4286000649 256100 \n'
现在PIPE
是空的,所以我将如何获得行数,直到我不再使用zcat
。
我可以通过在子进程中运行两次 zcat 并将第一个 zcat
输出重定向到 wc -l 并将第二个 zcat
的输出重定向到 cksum
来很好地做到这一点。但是zcat
是基于磁盘 IO 的,速度很慢。所以我想避免它。
【问题讨论】:
【参考方案1】:在 Python 中实现tee
命令的一种简单方法是手动写入子进程:
import gzip
from subprocess import Popen, PIPE
# zcat ABC_C_TPM_26122014.data.gz | tee >(wc -l) >(cksum)
with gzip.open("ABC_C_TPM_26122014.data.gz", "rb") as input_file:
wc = Popen(['wc', '-l'], stdin=PIPE, bufsize=1, close_fds=True)
cksum = Popen(['cksum'], stdin=PIPE, bufsize=1, close_fds=True)
line_count = 0
for line_count, line in enumerate(input_file, start=1):
wc.stdin.write(line)
cksum.stdin.write(line)
wc.stdin.close()
cksum.stdin.close()
wc.wait()
cksum.wait()
print("Line count in the parent: %d" % line_count)
如果输入中的行可能很大,那么您可以分块读取输入:chunk = input_file.read(chunk_size)
而不是逐行 (b'\n'
)。
【讨论】:
>>> from subprocess import Popen, PIPE >>> import gzip >>> >>> with gzip.open("cbp12co.csv.gz", "rb") as input_file: .. . wc = Popen(['wc', '-l'], stdin=PIPE, bufsize=1, close_fds=True) ... cksum = Popen(['cksum'], stdin=PIPE, bufsize=1, close_fds =True) ... line_count = 0 ... 对于 line_count, line in enumerate(input_file, start=1): ... wc.stdin.write(line) ... cksum.stdin.write(line) .. . wc.stdin.close() ... cksum.stdin.close() ... wc.wait() 文件“以上是关于将子进程的标准输出重定向到 2 个或更多子进程的标准输入的主要内容,如果未能解决你的问题,请参考以下文章