gzip.open作为subprocess.Popen的stdin

时间:2017-05-10 15:00:49

标签: python subprocess

我试图使用subprocess.Popen在python中启动程序,stdin是一些常规文本文件,就像这样。

subprocess.Popen(args, stdout=stdoutFile, stderr=stderrFile, stdin=open(TEXT_FILE))

它工作得很好。但是如果我尝试打开一个gzip压缩文件,我的进程就会失败。

import gzip
subprocess.Popen(args, stdout=stdoutFile, stderr=stderFile, stdin=gzip.open(GZFILE)) 

我不确定为什么。我的流程认为它没有获得任何数据。

知道为什么吗?难道2不可以互换吗?

2 个答案:

答案 0 :(得分:3)

如果传递gzip.open(..)的返回值,则将其内部文件描述符传递给该文件;从子流程中读取它将返回原始数据,而不是解压缩数据。

您需要将解压缩的数据传递给子流程'标准输入:

subprocess.Popen(args, stdout=stdoutFile, stderr=stderFile,, stdin=subprocess.PIPE)
with gzip.open(GZFILE) as f:
    shutil.copyfileobj(f, p.stdin)
# p.stdin.close()  # to denote the end of the file.

答案 1 :(得分:1)

就像@falsetru所说,Popen使用原始gzip数据而不是解压缩数据。这是一个完整的例子:

#!/usr/bin/env python3


import gzip
import subprocess
import shutil


filename = 'testfile'
data = 'Hello\n'

# Create some test files
with open(filename, 'w') as f:
    f.write(data)

with gzip.open(filename + '.gz', 'wt') as f:
    f.write(data)

# Make sure we can read them:
with open(filename) as f:
    d = f.read()
    print(d == data, d)

with gzip.open(filename + '.gz', 'rt') as f:
    d = f.read()
    print(d == data, d)

# See what Popen does with the files given as stdin
with open(filename) as f:
    result = subprocess.Popen('hexdump -C'.split(), stdin=f,
                              stdout=subprocess.PIPE)
    print(result.stdout.read().decode())

with gzip.open(filename + '.gz') as f:
    result = subprocess.Popen('hexdump -C'.split(), stdin=f,
                              stdout=subprocess.PIPE)
    print(result.stdout.read().decode())


# Fix the problem like this...
p = subprocess.Popen('hexdump -C'.split(),
                     stdout=subprocess.PIPE,
                     stdin=subprocess.PIPE)
with gzip.open(filename + '.gz', 'rb') as f:
    with p.stdin:
        shutil.copyfileobj(f, p.stdin)
print(p.stdout.read().decode())

# You can use the same pattern for the regular files, too:
p = subprocess.Popen('hexdump -C'.split(),
                     stdout=subprocess.PIPE,
                     stdin=subprocess.PIPE)
with open(filename, 'rb') as f:
    with p.stdin:
        shutil.copyfileobj(f, p.stdin)
print(p.stdout.read().decode())

输出:

$ ./subprocess_gzip_stdin.py
True Hello

True Hello

00000000  48 65 6c 6c 6f 0a                                 |Hello.|
00000006

00000000  1f 8b 08 08 fc 30 13 59  02 ff 74 65 73 74 66 69  |.....0.Y..testfi|
00000010  6c 65 00 f3 48 cd c9 c9  e7 02 00 16 35 96 31 06  |le..H.......5.1.|
00000020  00 00 00                                          |...|
00000023

00000000  48 65 6c 6c 6f 0a                                 |Hello.|
00000006

00000000  48 65 6c 6c 6f 0a                                 |Hello.|
00000006