По коду разбросаны if DEBUG: print() для вывода разной полезной информации. Некрасиво. А как еще?
нужно как-то выводить отладочную информацию.
Евгений
Предположим, наша программа должна выводить в консоль отладочную информацию: сколько времени ушло на скачивание страницы из Интернета, каков статус ответа и прочее. Вариантов действия у нас несколько.
Первый вариант, он же самый простой, — это раскидать по коду отладочные print
, а перед очередным коммитом не забыть их удалить. Вполне рабочая схема, у неё даже название свое есть - “отладка принтами”. Сложности начинаются когда:
- раз за разом приходится дописывать одни и те же вызовы
print
; - пользователю тоже иногда нужен вывод дополнительной информации в консоль.
Есть второй вариант — по коду раскидать конструкции вида:
if app_cfg['LOG_MOD']:
print('Data fetching took {}'.format(timeout_in_secs))
У такого кода есть несколько проблем:
- кода получается много, куча конструкций
if
; - повсюду приходится таскать за собой
app_cfg
, чтобы иметь возможность динамической настройки программы средствами argparse.
Еще один способ — использовать стандартную библиотеку logging. Она решает все эти проблемы. Вот пример использования:
import logging, requests
def fetch_article(slug):
response = requests.get('http://example.com/article/{}'.format(slug))
logging.info('HTTP STATUS {}'.format(response.status_code))
logging.debug(response.text)
...
В таком коде можно централизованно включить/выключить вывод отладочной информации в консоль. Например, включить вывод info сообщений:
# lets output INFO, WARNING, ERROR and CRITICAL messages
logging.basicConfig(level=logging.INFO)
Если мы хотим вдобавок к info вывести все debug сообщения:
# lets output totally all messages: DEBUG, INFO, WARNING, ERROR and CRITICAL
logging.basicConfig(level=logging.DEBUG)
В конечном счете все это позволяет легко настраивать логгирование через аргументы скрипта:
VERBOSITY_TO_LOGGING_LEVELS = {
0: logging.WARNING,
1: logging.INFO,
2: logging.DEBUG,
}
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('--verbose', '-v', action='count', default=0)
args = parser.parse_args()
logging_level = VERBOSITY_TO_LOGGING_LEVELS[args.verbose]
logging.basicConfig(level=logging_level)
...
При вызове python myscript.py -v
в консоли появятся info сообщения. При вызове python myscript.py -vv
— все сообщения включая debug.
Все сказанное выше справедливо для вывода вспомогательной информации. Для основной функциональности есть старый добрый print()
.
Модуль logging еще много чего умеет, и все это описано в документации и в туториале. Особенно часто используется возможность module-level logger. А вот логирование в файл, чему так много уделено внимания в документации, используют редко. Дело в том что stdout и stderr легко поддаются перенаправлению в файл. Кроме того, в systemd встроен логгер journald с продвинутыми механизмами фильтрации, поиска по логу, ротации и прочим. И этот journald считывает лог программ из stdout и stderr.
Попробуйте бесплатные уроки по Python
Получите крутое код-ревью от практикующих программистов с разбором ошибок и рекомендациями, на что обратить внимание — бесплатно.
Переходите на страницу учебных модулей «Девмана» и выбирайте тему.