如何使用python以与底层库相媲美的速度使用gzip/gunzip文件?Python中更快,更好的gunzip(和一般文件输入/输出)
tl;dr - Use shutil.copyfileobj(f_in, f_out).
我解压缩* .gz文件解作为一个更大的一系列文件处理的一部分,和分析,试图让蟒蛇进行“接近”内置的脚本。由于我正在使用的数据量很大,这很重要,而且这似乎是一个很重要的理解。
使用在500MB〜在 'gunzip解' bash命令如下收益:
$time gunzip data.gz -k
real 0m24.805s
一个天真的Python实现是这样的:
with open('data','wb') as out:
with gzip.open('data.gz','rb') as fin:
s = fin.read()
out.write(s)
real 2m11.468s
不读取整个文件到内存:
with open('data','wb') as out:
with gzip.open('data.gz','rb') as fin:
out.write(fin.read())
real 1m35.285s
检查本地计算机缓冲区大小:
>>> import io
>>> print io.DEFAULT_BUFFER_SIZE
8192
使用缓冲:
with open('data','wb', 8192) as out:
with gzip.open('data.gz','rb', 8192) as fin:
out.write(fin.read())
real 1m19.965s
使用尽可能多的缓冲地:
with open('data','wb',1024*1024*1024) as out:
with gzip.open('data.gz','rb', 1024*1024*1024) as fin:
out.write(fin.read())
real 0m50.427s
所以很明显它是缓冲/ IO约束。
我有一个适度复杂的版本,运行在36秒,但涉及预先分配的缓冲区和严密的内部循环。我希望有一个“更好的方法”。
上面的代码是合理和清晰的,尽管仍比bash脚本慢。但是,如果有一个非常迂回或复杂的解决方案,它不适合我的需求。我主要的警告是我想看到一个“pythonic”的答案。
当然,总是有这种解决方案:
subprocess.call(["gunzip","-k", "data.gz"])
real 0m24.332s
但对于这个问题的目的,是有处理文件“pythonically”的一个更快的方法。
有时python并不总是答案,那有什么问题? –
你的例子确实没有任何意义:python示例的所有三个例子1)只是复制并且根本不解压2)一次将文件读入内存3)不受io缓冲的限制。此外,'gunzip'和cpython的'gzip'模块使用完全相同的底层库 – user2722968
感谢您的支持。为必要的编辑道歉。我提前提交了提交。 1)错过了我的工作代码中的gzip前缀。现在添加。 2/3)通过缓冲它提高了2倍的速度。 4)是的,它确实使用底层库,所以我试图理解它为什么这么慢,特别是考虑到子进程版本和底层库一样快。 4b)foo.gz是来自样本的剪切和粘贴,现在已经修复。 5.)8219是一个错字。应该是8192,这对应于系统的缓冲区大小并增加了小的速度增加。 – JHiant