从 Popen 捕获输出

Capturing output from Popen

也许我需要的是对 STDOUT 的一般解释,但这是我的问题。我需要 运行 python 中的 shell 脚本对一堆文件,并解析输出。如果我 运行:

from itertools import combinations
from subprocess import Popen

for pair in combinations(all_ssu, 2):
    Popen(
        ['blastn',
        '-query', 'tmp/{0}.fna'.format(pair[0]),
        '-subject', 'tmp/{0}.fna'.format(pair[1]),
        '-outfmt', '6 qseqid sseqid pident'
        ],
    )

... 它似乎工作得很好(注意:all_ssu 本质上是一个文件名列表)。 shell 打印了一堆我想比较的数据行。那么我如何将打印的数据放入列表或数据框或其他东西中以便我可以使用它?

在查看文档和此处的一些其他问题后,stdout 标志似乎正在寻找文件对象,所以我尝试了:

from itertools import combinations
from subprocess import Popen
for pair in combinations(all_ssu, 2):
    out_file = open('tmp.txt', 'rw')
    Popen(
        ['blastn',
        '-query', 'tmp/{0}.fna'.format(pair[0]),
        '-subject', 'tmp/{0}.fna'.format(pair[1]),
        '-outfmt', '6 qseqid sseqid pident'
        ],
        stdout=out_file
    )
    for line in out_file.readlines():
        print line
    out_file.close()

这似乎也有效,只是我创建了不需要的临时文件。我尝试将变量 captured 设置为 None,然后将 stdout=captured 设置为 stdout=captured,但在这种情况下,它只是将 captured 设置为 0。我还尝试了 out = Popen(...) 没有stdout 标志,但同样,out 只是 int(0)。我也尝试过 PIPE,但无法弄清楚它的正面或反面。

所以问题是:如何直接捕获 Popen 的输出?

试试这个:

from itertools import combinations
from subprocess import Popen, PIPE
for pair in combinations(all_ssu, 2):
    out = Popen(
        ['blastn',
        '-query', 'tmp/{0}.fna'.format(pair[0]),
        '-subject', 'tmp/{0}.fna'.format(pair[1]),
        '-outfmt', '6 qseqid sseqid pident'
        ],
        stdout=PIPE
    ).communicate[0]
    print(out)

来自 How can I get terminal output in python?

STDOUT 只是程序的标准输出,它是程序打印的任何内容都将写入的文件。

如果您希望将输出作为列表,那么您可以在循环之前创建一个空列表(l = [] 或其他内容)并在循环的每次迭代结束时执行 l.append(out)

从 Python 2.7 开始,您可以使用 - subprocess.check_output

它returns将执行命令的输出返回为字节字符串。

例子-

>>> import subprocess
>>> s = subprocess.check_output(["echo","Hello World!"], shell=True)
>>> s
b'"Hello World!"\r\n'

我必须在 windows 上使用 shell=True 才能正常工作,但在 linux 上可能不需要。