我只是尝试使用Python 3.3运行此脚本。不幸的是,它的速度是Python 2.7的两倍。
#!/usr/bin/env python
from sys import stdin
def main():
for line in stdin:
try:
fields = line.split('"', 6)
print(fields[5])
except:
pass
if __name__ == '__main__':
main()
结果如下:
$ time zcat access.log.gz | python3 -m cProfile ./ua.py > /dev/null
real 0m13.276s
user 0m18.977s
sys 0m0.484s
$ time zcat access.log.gz | python2 -m cProfile ./ua.py > /dev/null
real 0m6.139s
user 0m11.693s
sys 0m0.408s
分析显示,额外的时间花费在打印上:
$ zcat access.log.gz | python3 -m cProfile ./ua.py | tail -15
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 0.000 0.000 <frozen importlib._bootstrap>:1594(_handle_fromlist)
196806 0.234 0.000 0.545 0.000 codecs.py:298(decode)
1 0.000 0.000 13.598 13.598 ua.py:3(<module>)
1 4.838 4.838 13.598 13.598 ua.py:6(main)
1 0.000 0.000 13.598 13.598 {built-in method exec}
1 0.000 0.000 0.000 0.000 {built-in method hasattr}
4300456 4.726 0.000 4.726 0.000 {built-in method print}
196806 0.312 0.000 0.312 0.000 {built-in method utf_8_decode}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
4300456 3.489 0.000 3.489 0.000 {method 'split' of 'str' objects}
$ zcat access.log.gz | python2 -m cProfile ./ua.py | tail -10
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 6.573 6.573 ua.py:3(<module>)
1 3.894 3.894 6.573 6.573 ua.py:6(main)
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
4300456 2.680 0.000 2.680 0.000 {method 'split' of 'str' objects}
如何避免这种开销?与UTF-8有关吗?
Python 3解码读取的数据stdin
并再次编码为stdout
;print()
在这里,与其说是unicode到字节的转换,倒不如说是功能要慢,反之亦然。
在您的情况下,您可能想绕过此方法而只处理字节;您可以BufferedIOBase
通过.buffer
属性访问基础实现:
from sys import stdin, stdout
try:
bytes_stdin, bytes_stdout = stdin.buffer, stdout.buffer
except AttributeError:
bytes_stdin, bytes_stdout = stdin, stdout
def main():
for line in bytes_stdin:
try:
fields = line.split(b'"', 6)
bytes_stdout.write(fields[5] + b'\n')
except IndexError:
pass
if __name__ == '__main__':
main()
现在,您必须使用stdout.write()
如print()
上写入坚持stdout
TextIOBase
执行。
请注意,.split()
现在使用的是字节字面量b'"'
,我们也编写了字节字面量b'\n'
(通常由by照顾print()
)。
以上与Python 2.6及更高版本兼容。Python 2.5不支持该b
前缀。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句