创建并管道类似文件的对象作为命令的输入

时间:2015-06-17 12:04:01

标签: python linux file subprocess

如果可能的话,我正在寻找更好的方法:

import subprocess

f = open('temp.file', 'w+')
f.write('hello world')
f.close()

out = subprocess.check_output(['cat', 'temp.file'])

print out

subprocess.check_output(['rm', 'temp.file'])

在这个例子中,我正在创建一个文件,并将其作为输入传递给cat(实际上它不是cat我正在运行,而是一些其他程序解析输入pcap文件)。

我想知道的是,Python中是否有一种方法可以创建一个包含某些内容的“类文件对象”,并将此类文件对象作为输入传递给命令行程序。如果有可能,我认为它比将文件写入磁盘然后删除该文件更有效。

4 个答案:

答案 0 :(得分:3)

如果程序配置为从stdin读取,您可以使用Popen.communicate

>>> from subprocess import Popen, PIPE
>>> p = Popen('cat', stdout=PIPE, stdin=PIPE, stderr=PIPE)
>>> out, err = p.communicate(input=b"Hello world!")
>>> out
'Hello world!'

答案 1 :(得分:3)

check_output使用stdin输入参数指定类似文件的对象以连接到进程的标准输入。

with open('temp.file') as input:
    out = subprocess.check_output(['cat'], stdin=input)

此外,没有必要支持运行rm;您可以直接从Python中删除文件:

os.remove('temp.file')

答案 2 :(得分:3)

您可以写入TemporaryFile

import subprocess
from tempfile import TemporaryFile
f = TemporaryFile("w")
f.write("foo")
f.seek(0)
out = subprocess.check_output(['cat'],stdin=f)

print(out)
b'foo'

如果你只想写一个像object这样的文件并获取内容:

from io import StringIO
f = StringIO()
f.write("foo")

print(f.getvalue())

答案 3 :(得分:1)

如果命令只接受文件名,如果它不读取其标准输入的输入,即如果你不能使用stdin=PIPE + .communicate()stdin=real_file那么你可以尝试/dev/fd/#文件名:

#!/usr/bin/env python3
import os
import subprocess
import threading

def pump_input(pipe):
    with pipe:
        for i in range(3):
            print(i, file=pipe)

r, w = os.pipe()
try:
    threading.Thread(target=pump_input, args=[open(w, 'w')]).start()
    out = subprocess.check_output(['cat', '/dev/fd/'+str(r)], pass_fds=[r])
finally:
    os.close(r)
print('got:', out)

没有内容触及磁盘。输入直接通过管道传递给子进程。

如果你有一个类似文件的对象不是真正的文件(否则,只是将其名称作为命令行参数传递),那么pump_input()可能如下所示:

import shutil

def pump_input(pipe):
    with pipe:
        shutil.copyfileobj(file_like_object, pipe)