【发布时间】:2014-09-23 01:39:11
【问题描述】:
似乎fileinput.input 的速度至少是zcat 的两倍,即使设置了缓冲也是如此。 问题:有没有什么我可以在不编写大量代码的情况下使其高效运行的方法?我所做的测试是从 urandom 获取数据,
"""generate.py"""
import base64
with open('/dev/urandom', 'rb') as f:
for _ in xrange(102400):
print(base64.b64encode(f.read(1024)))
运行它并通过 gzip 管道输出,
> python generate.py | gzip - > test_input.gz
zcat时间
> time zcat test_input.gz > /dev/null
zcat test_input.gz > /dev/null 1.56s user 0.02s system 99% cpu 1.576 total
文件输入时间
> time python -c 'import fileinput; list(fileinput.input(files=["test_input.gz"], openhook=fileinput.hook_compressed))'
python -c 3.13s user 0.16s system 99% cpu 3.293 total
这不仅仅是 fileinput.input() 速度慢,因为它从标准输入读取时没问题,
> time zcat test_input.gz | python -c 'import fileinput; list(fileinput.input())'
zcat test_input.gz 1.64s user 0.04s system 96% cpu 1.736 total
python -c 'import fileinput; list(fileinput.input())' 0.39s user 0.17s system 31% cpu 1.800 total
我搞砸了bufsize=,但没有运气。
写了很多代码
我在 google 上闲逛,认为 gzip 本身很慢,发现如果我做一些手动缓冲就可以了,
"""read_buffered_manual.py"""
import gzip
def input_buffered_manual(filename, buf_size=32 * 1024):
fd = gzip.open(filename)
try:
remaining = ''
while True:
input_ = fd.read(buf_size)
if not input_:
if remaining:
yield remaining
return
lines = input_.split('\n')
lines[0] = remaining + lines[0]
remaining = lines.pop()
for line in lines:
yield line
finally:
fd.close()
for line in input_buffered_manual("test_input.gz"):
print line
这个速度很快,甚至比 zcat 还要快,
> time python read_buffered_manual.py > /dev/null
python read_buffered_manual.py > /dev/null 1.40s user 0.04s system 99% cpu 1.461 total
【问题讨论】:
标签: python performance file-io gzip