将子进程的标准输出重定向到 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 个或更多其他subprocesses(比如proc2proc3)蟒蛇。

嗨, 我需要 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() 文件“”,第 10 行 wc.wait() ^ SyntaxError: invalid syntax >>>跨度> 将代码保存到文件中。复制粘贴不适用于普通 Python REPL 中的多行代码

以上是关于将子进程的标准输出重定向到 2 个或更多子进程的标准输入的主要内容,如果未能解决你的问题,请参考以下文章

重定向子进程标准输出

在C中重定向子进程的文件输出

使用带有标准输入和标准输出重定向的 2 进程管道时如何避免标准输入上的重复输入

如何获取子进程的输出

使用重定向的标准输入处理子进程中的 kbhit

将进程的标准输出重定向到多个管道