gzip.open作为标准子流程.Popen

2024-04-20 06:18:03 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图用python启动一个程序,其中subprocess.Popenstdin是一些常规的文本文件,如下所示。在

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

而且效果很好。但是如果我试图打开一个gzip文件,我的进程就会失败。在

^{pr2}$

我不知道为什么。我的程序认为它没有得到任何数据。在

知道为什么吗?2不应该互换吗?在


Tags: text程序stderrstdinstdoutargsopen常规
2条回答

正如@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())

输出:

^{pr2}$

如果传递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.

相关问题 更多 >