我有一些数据,我想gzip,uuencode然后打印到标准输出。我基本上拥有的是:
compressor = Popen("gzip", stdin = subprocess.PIPE, stdout = subprocess.PIPE)
encoder = Popen(["uuencode", "dummy"], stdin = compressor.stdout)
我向压缩器提供数据的方式是通过compress.stdin.write(stuff)。
我真正需要做的是将EOF发送到压缩器,我不知道该怎么做。
在某些时候,我尝试了compress.stdin.close()但是这不起作用 - 当压缩器直接写入文件时它很有效,但在上面的情况下,进程不会终止并停止在compress.wait()。
连连呢?在这种情况下,gzip就是一个例子,我真的需要做一些事情来管理一个进程的输出到另一个进程。
注意:我需要压缩的数据不适合内存,所以沟通在这里不是一个好选择。另外,如果我只是运行
compressor.communicate("Testing")
在上面的2行之后,它仍然会挂起错误
File "/usr/lib/python2.4/subprocess.py", line 1041, in communicate rlist, wlist, xlist = select.select(read_set, write_set, [])
答案 0 :(得分:4)
我怀疑问题在于您打开管道的顺序。 UUEncode很有趣的是,如果你没有以正确的方式传入管道,它会发出呜呜声(尝试在Popen调用中自己启动darn的东西,只用PIPE作为stdin和stdout看爆炸)
试试这个:
encoder = Popen(["uuencode", "dummy"], stdin=PIPE, stdout=PIPE)
compressor = Popen("gzip", stdin=PIPE, stdout=encoder.stdin)
compressor.communicate("UUencode me please")
encoded_text = encoder.communicate()[0]
print encoded_text
begin 644 dummy
F'XL(`%]^L$D``PL-3<U+SD])5<A-52C(24TL3@4`;2O+"!(`````
`
end
你是对的,顺便说一句......没有办法向管道发送通用EOF。毕竟,每个程序都确实定义了自己的EOF。这样做的方法是关闭管道,就像你想要的那样。
编辑:我应该更清楚uuencode。作为shell程序,它的默认行为是期望控制台输入。如果在没有“实时”传入管道的情况下运行它,它将阻止等待控制台输入。通过打开编码器,在压缩机管道中发送材料之前,编码器阻止等待您开始键入。 Jerub是对的,因为有阻塞的东西。答案 1 :(得分:3)
这不是你应该直接在python中做的事情,关于如何工作的怪癖使得用shell做这个更好的主意。如果你可以使用subprocess.Popen(“foo | bar”,shell = True),那就更好了。
可能发生的事情是gzip还无法输出所有输入,并且在stdout写入完成之前,进程不会退出。
如果使用strace,您可以查看进程阻止的系统调用。使用ps auxwf
来发现哪个进程是gzip进程,然后使用strace -p $pidnum
查看它正在执行的系统调用。请注意,stdin是FD 0,stdout是FD 1,您可能会看到它在这些文件描述符上读取或写入。
答案 2 :(得分:1)
如果您只想压缩并且不需要文件包装器,请考虑使用zlib模块
import zlib
compressed = zlib.compress("text")
shell = True和unix管道建议的任何原因都不起作用?
from subprocess import *
pipes = Popen("gzip | uuencode dummy", stdin=PIPE, stdout=PIPE, shell=True)
for i in range(1, 100):
pipes.stdin.write("some data")
pipes.stdin.close()
print pipes.stdout.read()
似乎有用