2013-05-16 2 views
1

У меня есть приложение Python, написанное на фреймворке Pyramid.Оптимизация кода регистрации Python

Мы действительно воспользуйтесь регистрацией этого (для отладки), используя стандартную библиотеку импорта.

Как мы рассматриваем материал на производстве, кажется, что из нашей деятельности по регистрации существует довольно много накладных расходов. Все форматирование строк и петли складываются. Я бы хотел его удалить, но мы не можем - нам действительно нужно удержать его для тестирования и иногда нужно отлаживать производственную среду.

Мне интересно, есть ли у кого-то эффективные стратегии для минимизации регистрации при необходимости, поэтому этот код может быть «оптимизирован» во время выполнения на нашей производственной среде и просто не запускаться.

Например, под mod_perl, компилятор "оптимизировать прочь" заявления работать под Ложные констант

в psuedocode ... (я не прикасался Perl в течение длительного времени!)

use constant DEBUG => False ; 
if (DEBUG) { 
     log.debug("stuff here " + string); 
} 

или

use constant DEBUG => False ; 
DEBUG && log.debug("stuff here " + string); 

в этих сценариях, призыв к log.debug и даже строка интерполяции никогда не произойдет.

Может ли кто-нибудь рекомендовать эффективный метод имитации этого поведения в Python?

+0

спасибо Martijn, это отличный совет. Вы должны передать его в качестве ответа. –

+0

Добавлено с некоторым расширением. –

ответ

6

Использование __debug__. Этот флаг установлен в False, когда Python запускается с флагом командной строки -O, а Python, кроме того, оптимизирует код отладки во время компиляции. I wrote a blog post on it пару месяцев назад.

+1

Спасибо, @kindall - это отличный трюк. вы не представляете, насколько я сейчас улыбаюсь. –

7

Не используйте конкатенацию, если вы можете использовать log.debug('stuff here %s', string); модуль протоколирования откладывает интерполяцию до фактического форматирования строки при регистрации. Если уровень журнала DEBUG отключен, интерполяция не выполняется.

Вы также можете проверить уровень протоколирования, чтобы избежать сбора дорогостоящей информации протоколирования, если не требуется:

if logger.isEnabledFor(logging.DEBUG): 
    logger.debug('Message with %s, %s', expensive_func1(), 
             expensive_func2()) 

См optimization section of the Logging HOWTO.

+1

Печально, что вы должны использовать 'if' в своем коде. Было бы возможно, чтобы «logger» был достаточно умен, чтобы принимать «logger.debug (« Сообщение с% s,% s »,« дорогой_func1, дорогой_func2 ») и при необходимости вызывать функцию func. Я думаю, вы могли бы сделать это с помощью обертки, но я ненавижу, сколько шаблонов для регистрации. Это заставляет людей избегать регистрации или делать это плохо. –

+0

На самом деле не обязательно использовать явное, если полностью отключить выполнение кода ведения журнала в оптимизированном режиме (см. Мой ответ ниже). Интересно, есть ли у моего ответа какие-то недостатки, которые я не вижу (кроме явного злоупотребления 'assert'). –

+0

@ peschü: ну, само злоупотребление уже является одним из таких недостатков; читаемость определенно страдает. –

0

Я предлагаю использовать для этой цели assert, так как он прекрасно оптимизирован в оптимизированном режиме.

В этом случае нет необходимости вручную проверять, включен ли уровень ведения журнала. Это особенно полезно при выполнении дорогостоящих операций форматирования, которые могут быть полезны для ведения журнала (например, с модулем pprint).

Пример: (. Часть or True убеждается утверждение не обязательно)

Вместо

logging.debug('my message %s', pprint.pformat(mycomplexdata))

можно было бы написать

assert(logging.debug('my message %s', pprint.pformat(mycomplexdata)) or True)

В этом случае можно использовать .format без штрафных санкций при работе с -O.

assert(logging.debug('my message {}'.format(pprint.pformat(mycomplexdata))) or True)

Все в утверждают() оптимизирован прочь при запуске питона с -O.

+0

'assert' - это инструкция, а не функция:' assert logging.debug ('my message% s', pprint.pformat (mycomplexdata)) или True' –

+1

Вместо того, чтобы злоупотреблять 'assert', используйте константу [' __debug__' ] (https://docs.python.org/3/library/constants.html#__debug__), поэтому используйте 'if __debug __:'. Компилятор будет либо включать блок под 'if', либо полностью исключить его (так что ** никакой фактический тест' if' не включен **). –

+0

Другими словами, использование 'assert' является уродливой уродливой версией использования принятого ответа. –

Смежные вопросы