Python等效于使用管道将文件输出到Perl中的gzip

Python等效于使用管道将文件输出到Perl中的gzip,python,gzip,pipe,compression,filehandle,Python,Gzip,Pipe,Compression,Filehandle,我需要弄清楚如何用Python将文件输出写入压缩文件,类似于下面的两行代码: open ZIPPED, "| gzip -c > zipped.gz"; print ZIPPED "Hello world\n"; 在Perl中,它使用Unix gzip将打印到压缩文件句柄的内容压缩到文件“ZIPPED.gz” 我知道如何使用“import gzip”在Python中这样做: import gzip zipped = gzip.open("zipped.gz", 'wb') zipped.

我需要弄清楚如何用Python将文件输出写入压缩文件,类似于下面的两行代码:

open ZIPPED, "| gzip -c > zipped.gz";
print ZIPPED "Hello world\n";
在Perl中,它使用Unix gzip将打印到压缩文件句柄的内容压缩到文件“ZIPPED.gz”

我知道如何使用“import gzip”在Python中这样做:

import gzip
zipped = gzip.open("zipped.gz", 'wb')
zipped.write("Hello world\n")
from subprocess import Popen, PIPE
f = open('zipped.gz', 'w')
pipe = Popen('gzip', stdin=PIPE, stdout=f)
pipe.communicate('Hello world\n')
f.close()

然而,这是非常缓慢的。根据profiler,使用该方法占用了我90%的运行时间,因为我正在将200GB的未压缩数据写入各种输出文件。我知道文件系统可能是问题的一部分,但我想通过使用Unix/Linux压缩来排除它。这部分是因为我听说使用同一个模块进行解压缩也很慢。

使用是官方的一种方法,任何其他纯python方法都不可能走得更快。这一点尤其正确,因为数据的大小排除了内存选项。最有可能的是,最快的方法是将完整的文件写入磁盘,并使用调用该文件上的gz。

ChristopheD建议使用是对这个问题的适当回答。但是,我不清楚它是否能解决您的性能问题。您必须测量新代码的性能才能确定

要转换示例代码,请执行以下操作:

import subprocess

p = subprocess.Popen("gzip -c > zipped.gz", shell=True, stdin=subprocess.PIPE)
p.communicate("Hello World\n")

由于需要向子进程发送大量数据,所以应该考虑使用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

您也可以在中找到有用的讨论。

尝试以下内容:

import gzip
zipped = gzip.open("zipped.gz", 'wb')
zipped.write("Hello world\n")
from subprocess import Popen, PIPE
f = open('zipped.gz', 'w')
pipe = Popen('gzip', stdin=PIPE, stdout=f)
pipe.communicate('Hello world\n')
f.close()

除了
@srgerg
的答案之外,我还想通过禁用shell选项
shell=False
来应用相同的方法,这也是在@Moishe-Lettvin的答案上完成的,建议在()上执行


请注意,我最初使用此
p1
s输出作为
git diff


p1=subprocess.Popen([“git”,“diff”],stdout=subprocess.PIPE)

确保在比较速度时使用相同的压缩级别。默认情况下,LinuxGzip使用级别6,而python使用级别9。我在Python3.6.8中使用gzip版本1.5测试了这一点,从MySQL转储压缩了600MB的数据。使用默认设置:

python模块耗时9.24秒,生成一个47.1 MB的文件
子进程gzip需要8.61秒,文件大小为48.5 MB

# subprocess method
start = time.time()
with open(outfile, 'wb') as f:
    subprocess.run(['gzip'], input=dump, stdout=f, check=True)
print('subprocess finished after {:.2f} seconds'.format(time.time() - start))

# gzip method
start = time.time()
with gzip.open(outfile2, 'wb', compresslevel=6) as z:
    z.write(dump)
print('gzip module finished after {:.2f} seconds'.format(time.time() - start))
将其更改为第6级以便匹配后:
python模块耗时8.09秒,生成一个48.6 MB的文件
子进程gzip需要8.55秒,文件大小为48.5 MB

# subprocess method
start = time.time()
with open(outfile, 'wb') as f:
    subprocess.run(['gzip'], input=dump, stdout=f, check=True)
print('subprocess finished after {:.2f} seconds'.format(time.time() - start))

# gzip method
start = time.time()
with gzip.open(outfile2, 'wb', compresslevel=6) as z:
    z.write(dump)
print('gzip module finished after {:.2f} seconds'.format(time.time() - start))

您需要用纯Python完成吗,或者您可以满足于在文件系统上调用二进制文件(在Python中,您会使用子流程模块)?我不喜欢用Python完成,因为纯Python方法太慢。您是否在200 GB的未压缩数据上从shell运行gzip程序?我希望在CPU利用率为90-100%的情况下,这需要相当多的挂钟时间——在我的Windows机器上,它每GB运行约1分钟,而Python gzip模块每GB运行约2分钟。Dave,是的,这是我所追求的2分钟和1分钟之间的差异。我验证了这种方法在1GB高度可压缩文件上的速度快33%。与gzip.open相比,这是一个很好的改进。下面是我用来测试它的代码:import subprocess text=“fjlaskfjioewru oijf alksfjlkqs jrjweqoirjwoiefjlkadsfj afjf\n”for I in xrange(1,25):text+=text p=subprocess.Popen(“gzip-c>zipped.gz”,shell=True,stdin=subprocess.PIPE)`p.stdin.write(text)p.communicate()开放时间:12.109u 1.194s 0:13.37 99.4%0+0k 0+0io 0pf+0w以上代码的时间:8.379u 2.602s 0:10.17 107.8%0+0k 0+0io 0pf+0wBe请务必接受您最喜欢的答案:-)。我们都喜欢这个额外的代表。出于好奇,当我使用这个方法而不是gzip.open时,一个大型测试的运行时间从6h43m下降到4h31m。这是同一台机器上的苹果对苹果。这大约快了33%,这正是我在较小的测试用例中看到的。谢谢大家@bu11d0zer:您应该使用pastebin进行此类操作: