【问题标题】:Can I use an opened gzip file with Popen in Python?我可以在 Python 中将打开的 gzip 文件与 Popen 一起使用吗?
【发布时间】:2011-02-13 12:55:44
【问题描述】:

我有一个从标准输入读取的小命令行工具。 在命令行上我会运行...

./foo < bar

或者...

cat bar | ./foo

使用 gzip 文件我可以运行

zcat bar.gz | ./foo

在 Python 中我可以做到...

Popen(["./foo", ], stdin=open('bar'), stdout=PIPE, stderr=PIPE)

但我做不到

import gzip
Popen(["./foo", ], stdin=gzip.open('bar'), stdout=PIPE, stderr=PIPE)

我不得不跑了

p0 = Popen(["zcat", "bar"], stdout=PIPE, stderr=PIPE)
Popen(["./foo", ], stdin=p0.stdout, stdout=PIPE, stderr=PIPE)

我做错了吗? 为什么我不能使用 gzip.open('bar') 作为 Popen 的标准输入参数?

【问题讨论】:

    标签: python scripting subprocess


    【解决方案1】:

    因为子进程的 'stdin' 和 'stdout' 需要文件描述符(这是一个数字),这是一个操作系统资源。这被以下事实所掩盖:如果您传递一个对象,子进程模块会检查该对象是否具有“fileno”属性,如果有,它将使用它。

    “gzip”对象不是操作系统提供的。打开的文件是,套接字是,管道是。 Gzip 对象是一个提供 read() 和 write() 方法但没有 fileno 属性的对象。

    你可以看一下子进程的communicate()方法,你可能想用它。

    【讨论】:

    • 是的,我实际上是在使用 p = Popen([...]) 然后读取 p.communicate()[0]。另外,我的程序不叫 foo 并且我的输入文件不叫 bar ;-) 所以你是说没有简单的解决方法?我觉得很奇怪 Popen(["./foo", ], stdin=gzip.open('bar'), stdout=PIPE, stderr=PIPE) 工作(尽管返回错误的输出)并且没有引发异常。即使它可能没有 fileno 属性,它也会对它做一些事情。
    • 子流程模块中的“PIPE”和“STDOUT”属性是“特殊常量”;在 stderr=STDOUT 的情况下,常量表示应该传递给客户端进程的文件号应该相同,即作为标准输出传递。在 PIPE 的情况下,使用操作系统的“pipe()”命令创建一个新的文件号,管道的一半(实际上是 2 个数字)传递给客户端进程,一个给你。无论写入一个部分,都可以从另一部分读取。您无法轻松解决它,需要更多的编程。
    • Popen(["./foo", ], stdin=gzip.open('bar'), stdout=PIPE, stderr=PIPE) 工作并返回错误的输出,因为它确实实现了 fileno ,只是实现只是返回底层gzip文件的fileno。这意味着子进程会将其标准输入直接设置为压缩文件,而不是未压缩的流。
    猜你喜欢
    • 1970-01-01
    • 2011-06-13
    • 2012-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多