Почему печать настолько медленная в Python 3.3 и как я могу ее исправить?

Я просто попытался запустить этот скрипт с помощью 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?

One Solution collect form web for “Почему печать настолько медленная в Python 3.3 и как я могу ее исправить?”

Python 3 декодирует данные, считываемые из stdin и снова кодирует в stdout ; это не так много функции print() которая здесь медленнее, чем преобразование unicode-to-bytes и наоборот.

В вашем случае вы, вероятно, хотите обойти это и использовать только байты; вы можете получить доступ к базовой реализации BufferedIOBase с .buffer атрибута .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() настаивает на записи в реализацию TextIOBase .

Обратите внимание, что .split() теперь использует буквенный .split() b'"' и мы также пишем .split() литерал b'\n' (о котором обычно будет заботиться print() ).

Вышеупомянутое совместимо с Python 2.6 и выше. Python 2.5 не поддерживает префикс b .

  • Чтение данных файла Unicode с символами спецификации в Python
  • Преобразование кодовых точек Unicode в символ Unicode с использованием Python 3.3.1
  • Регулярные выражения и Unicode в Python: разница между sub и findall
  • Как изменить строку на Unicode в Python 2?
  • Как преобразовать формат файла из Unicode в ASCII с помощью Python?
  • Печать строки арабского Unicode в Python (x, y)
  • Почему имена POST с Unicode отправляются правильно при использовании multipart / form-data?
  • Python Как исправить сломанную кодировку utf-8?
  • Python - лучший язык программирования в мире.