将子进程的stdout重定向到2个或更多子进程的stdin

时间:2015-01-02 10:30:01

标签: python subprocess named-pipes

基本上我想学习如何使用stdout subprocess proc1作为stdin作为subprocess的2个或更多其他proc2 es(在python中说proc3& zcat)。

您好, 我需要subprocess.PIPE一个.gz文件,并使用cksum发送给[hashroot@dev_server 12]$ zcat ABC_C_TPM_26122014.data.gz | tee >(wc -l) >(cksum)| tail -2 2020090579 112180 586 (unix实用程序)和行计数的输出。

我可以用bash这样做......

>>> 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'

我想在python中做同样的事情。

我一做到这一点......

PIPE

现在zcat为空,所以在我再次zcat之前我将如何计算行数。

我可以通过在子进程中运行两次zcat,并将第一个zcat输出重定向到wc -l,将第二个cksum的输出重定向到zcat来实现。但{{1}}基于磁盘IO并且速度很慢。所以我想避免它。

1 个答案:

答案 0 :(得分:2)

在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')。