在Python中使用管道将文件输出压缩为gzip的等效方法
我想知道怎么在Python里把文件输出写入一个压缩文件,类似下面这两行代码:
open ZIPPED, "| gzip -c > zipped.gz";
print ZIPPED "Hello world\n";
在Perl中,这个操作使用Unix的gzip来压缩你打印到“zipped.gz”这个文件的内容。
我知道在Python中可以用“import gzip”来实现,像这样:
import gzip
zipped = gzip.open("zipped.gz", 'wb')
zipped.write("Hello world\n")
不过,这种方法非常慢。根据性能分析工具的数据显示,使用这种方法占用了我90%的运行时间,因为我需要把200GB的未压缩数据写入多个输出文件。我知道文件系统可能是问题的一部分,但我想通过使用Unix/Linux的压缩方法来排除这个因素。部分原因是我听说用这个模块解压缩也很慢。
5 个回答
2
使用 gzip模块 是官方推荐的唯一方法,而且其他纯Python的方式可能不会更快。这尤其适用于当你的数据量很大,无法全部放在内存里的情况。最有可能的最快方法是把整个文件写入磁盘,然后用 subprocess 来调用 gz 对那个文件进行处理。
6
你可以试试这样做:
from subprocess import Popen, PIPE
f = open('zipped.gz', 'w')
pipe = Popen('gzip', stdin=PIPE, stdout=f)
pipe.communicate('Hello world\n')
f.close()
10
ChristopheD提到的使用 subprocess模块 的建议是个不错的答案。不过,我不太确定这是否能解决你的性能问题。你需要测量一下新代码的性能才能确认。
要转换你的示例代码:
import subprocess
p = subprocess.Popen("gzip -c > zipped.gz", shell=True, stdin=subprocess.PIPE)
p.communicate("Hello World\n")
因为你需要向子进程发送大量数据,所以你应该考虑使用 stdin
属性,这个属性是Popen对象的一部分。例如:
import subprocess
p = subprocess.Popen("gzip -c > zipped.gz", shell=True, stdin=subprocess.PIPE)
p.stdin.write("Some data")
# Write more data here...
p.communicate() # Finish writing data and wait for subprocess to finish
你可能还会觉得 这个问题 的讨论很有帮助。