Для чого потрібний Logger

Для чого потрібний Logger



Введення у logging на Python

У стандартній бібліотеці Python є чудовий пакет для логування – logging. У мережі існує думка, що він складний і налаштовувати його суцільний біль. У цій статті я спробую переконати вас у протилежному. Ми розберемо що являє собою цей пакет, вивчимо основні компоненти і закріпимо матеріал практичним прикладом.

Для чого потрібні логи?

Логи є рентген знімок виконання вашої програми. Чим детальніше балка, тим простіше розібратися в нестандартних ситуаціях, які можуть статися з вашим скриптом. Найбільш популярним прикладом логів є access логи веб-сервера, наприклад, Apache httpd або nginx. Приклад шматка access лога мого блога:

92.63.107.227 - - [04/Nov/2020:06:30:48 +0000] "GET /ru/hosted-open-vpn-server/ HTTP/1.1" 301 169 "-" "python-requests/2.11.1 " "-" 92.63.107.227 - - [04/Nov/2020:06:30:49 +0000] "GET /ru/data-engineering-course/ HTTP/1.1" 301 169 "-" "python-requests/2.11 .1" "-" 213.180.203.50 - - [04/Nov/2020:06:36:07 +0000] "GET/HTTP/1.1" 301 169 "-" "Mozilla/5.0 (compatible; YandexMetrika/2.0; +http://yandex.com/bots yabs01)" "-" 114.119.160.75 - - [04/Nov/2020:06:36:41 + 0000] "GET /robots.txt HTTP/1.1" 301 169 "-" "(compatible;PetalBot;+https://aspiegel.com/petalbot)" "10.179.80.67" 90.180.35.207 - - [04/ 2020:06:47:11 +0000] "GET/HTTP/1.0" 301 169 "-" "-" "-" 46.246.122.77 - - [04/Nov/2020:06:53:22 +0000] "GET / HTTP/1.1" 301 169 "" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/537.36 (KHTML, like Geck Chrome/66.0.3359.181 Safari/537.36" "-" 66.249.76.16 - - [04/Nov/2020:06:53:30 +0000] "GET / HTTP/1.1" 301 169 "-" "Mozilla ; Googlebot/2.1; +http://www.google.com/bot.html)" "-" [04/Nov/2020:07:11:19 +0000] "GET/HTTP/1.1" 301169" -" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, як Gecko) Chrome/49.0.2623.75 Safari/537.36 Google Favicon" "46.159.204.234" 71.6.167.142 - - [04/N0/5 / HTTP/1.1" 301 169 "-" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, як Gecko) Chrome/41.0.2228.0 Safari/537.36" "-"

Крім access логів, веб-сервер також пише error лог, там зберігається інформація про всі помилки при обробці HTTP запитів. Також і у ваших скриптах, логи можуть ділитися на інформаційні - виведення поточного стану виконання, налагоджувальну інформацію, і на логи з помилками - висновок винятків, помилок з додатковою інформацією для налагодження, що містить контекст).

logging та Python

Точкою входу в роботу з логуванням Python є бібліотека logging.На перший погляд може здатися, що бібліотека складна і заплутана, але витративши деякий час на її вивчення, можна переконатися у протилежному. Для мене logging – це класичний приклад дизайну ОВП, де композиція переважає над спадкуванням, тому у вихідному коді бібліотеки можна зустріти безліч функціональних класів. Мета цього туторіалу розібрати по кісточках кожен клас і об'єднати в єдиний механізм логування в Python. Почнемо-с.

Logger

Щоб почати роботу з logging необхідно імпортувати бібліотеку logging і викликати функцію getLogger, передавши їй ім'я майбутнього логера. Функція поверне інстанс об'єкта Logger. Логер це важіль за який ми смикаємо щоразу, коли нам потрібно записати інформацію в балку.

import logging logger = logging.getLogger('logger')

Зауважте, що функція getLogger приймає на вхід параметр - ім'я логера. Можна призначати будь-яке ім'я або __name__. Виклик getLogger з однаковою назвою поверне той самий інстанс логера.

Я рекомендую використовувати як аргумент __name__ , в цьому випадку не потрібно турбуватися, що різні модулі можуть посилатися на той самий логер.

Клас Logger надає назовні кілька способів для запису повідомлень різного рівня. Рівні необхідні розуміння контексту повідомлення/лога, що ми пишемо. У logging існує кілька рівнів:

  1. DEBUG — рівень налагоджувальної інформації, що часто допомагає при розробці програми на машині програміста.
  2. INFO - Рівень допоміжної інформації про хід роботи програми/скрипту.
  3. WARNING - Рівень попередження. Наприклад, ми можемо попереджати, що та чи інша функція буде видалена у майбутніх версіях вашої програми.
  4. ERROR - З таким рівнем розробники пишуть логи з помилками, наприклад, про те, що зовнішній сервіс недоступний.
  5. CRITICAL — рівень повідомлень, після яких робота програми тривати не може.

За замовчуванням у logging заданий рівень WARNING, це означає, що повідомлення рівня DEBUG і INFOігноруватимуться при записі в балку. Розробник може самостійно задати необхідний йому рівень логування через метод setLevel у інстансу Logger:

logger.setLevel(logging.DEBUG)

Методи для запису повідомлень з різними рівнями називаються за тим самим принципом:

logger.debug('debug info') logger.info('info') logger.warning('warning') logger.error('debug info') logger.critical('debug info')

Також є ще один метод - exception. Його бажано викликати у блоці except при обробці виключення. У цьому випадку він зможе вловити контекст виключення та записати його в лог:

try: 1/0 except : logger.exception('exception')

Handler

Завдання класу Handler та його нащадків обробляти запис повідомлень/логів. Тобто. Handler відповідає за те, куди будуть записані повідомлення. У базовому наборі logging надає ряд готових класів-обробників:

  • SteamHandler - запис у потік, наприклад, stdout або stderr.
  • FileHandler - запис у файл, клас має безліч похідних класів з різною функціональністю (ротація файлів логів за розміром, часом і т.д.)
  • SocketHandler — запис повідомлень у сокет через TCP
  • DatagramHandler — запис повідомлень у сокет UDP
  • SysLogHandler - запис у syslog
  • HTTPHandler — запис HTTP

Це далеко не повний перелік. Щоб переглянути все, перейдіть за посиланням вище. Для вказівки Handler необхідно в інстанса Logger викликати метод addHandler і передати туди інстанс класу Handler. В одного Logger інстансу може бути безліч обробників.

Приклад запису лога в stdout:

import sys import logging from logging import StreamHandler logger = logging.getLogger(__name__) logger.setLevel(logging.DEBUG) handler = StreamHandler(stream=sys.stdout) logger.addHandler(handler) logger.debug('debug

Якщо запустити цей скрипт, можна побачити повідомлення:

Ми бачимо повідомлення рівня DEBUG тому що завдання цей рівень у налаштуваннях. Якщо змінити його на INFO, то повідомлення пропаде:

logger.setLevel(logging.INFO)

Напевно ви звернули увагу, що ліг містить лише переданий рядок. Як зробити так, щоб у лозі була інформація про рівень лога, час запису?

Formatter

Formatter це ще один клас у сімействі logging, який відповідає за відображення лога. Якщо клас Handler відповідальний за те, куди відбуватиметься запис, клас Formatter відповідає на питання як буде записано повідомлення. За замовчуванням в лог пишеться голий рядок, який ми передаємо через методи debug, info і т.д. Давайте збагатимо наш лог додаткової метаінформації, наприклад, про час запису та рівень повідомлення. Formatter передається інстансу Handler через метод .setFormatter

import sys import logging from logging import StreamHandler, Formatter logger = logging.getLogger(__name__) logger.setLevel(logging.DEBUG) handler = StreamHandler(stream=sys.stdout) handler.setFormatter(Formatter(fmt='[%( s: %(levelname)s] %(message)s')) logger.addHandler(handler) logger.debug('debug information')

Запуск скрипта виведе на екран наступне повідомлення:

[2020-11-22 13:00:08,751: DEBUG] debug information

Зверніть увагу на рядок, який я передав під час ініціалізації інстансу Formatter :

[%(asctime)s: %(levelname)s] %(message)s

Це шаблон, який буде заповнений під час запису повідомлення в балку. Набір таких готових шаблонів можна переглянути в розділі LogRecord attributes.

Filter

Завдання класу фільтрувати повідомлення за заданою логікою розробником. Припустимо, що хочу записувати в лог повідомлення, що містять слово python . Щоб задати фільтр, необхідно викликати метод addFilter у інстансу Logger. Передати можна або інстанс класу, що реалізує метод filter або callable об'єкт (наприклад, функцію). На вхід прилетить інстанс класу LogRecord, це і є 1 повідомлення лога:

import sys import logging from logging import StreamHandler, Formatter, LogRecord def filter_python(record: LogRecord) -> bool: return record.getMessage().find('python') != -1 logger = logging.getLogger(__name__) logger. setLevel(logging.DEBUG) handler = StreamHandler(stream=sys.stdout) handler.setFormatter(Formatter(fmt='[%(asctime)s: %(levelname)s] %(message)s')) logger.addHandler( handler) logger.addFilter(filter_python) logger.debug('python debug information')

Наочно та зрозуміло, хіба logging може бути складним? 😎

LoggerAdapter

Адаптер необхідний передачі додаткової контекстної інформації при кожному запису лога через Logger. Наприклад, ви написали веб-додаток і вам необхідно в логи додатково передавати username користувача:

class CustomLoggerAdapter(LoggerAdapter): def process(self, msg, kwargs): return f' from ', kwargs logger2 = logging.getLogger('adapter') logger2.setLevel(logging.DEBUG) handler = StreamHandler(stream ) handler.setFormatter(Formatter(fmt='[%(asctime)s: %(levelname)s] %(message)s')) adapter = CustomLoggerAdapter(logger2, ) logger2.addHandler(handler) adapter.error('failed to save')

extra і не тільки

Рядки в логах це добре, а що якщо я хочу, крім рядка, додатково передавати відповідь від веб-сервера? Для цього можна використовувати аргумент extra при виклику методів debug, info і т.д. Давайте напишемо приклад висновку

logger.debug('debug info', extra=)

Тепер висновок значення ключа response можна вказати через Formatter (за умови, що response передається завжди):

Formatter(fmt='[%(asctime)s: %(levelname)s] %(message)s, response: %(response)s')

Аргумент extra зручний при написанні своїх кастомних обробників ліг (наприклад, відсилання ліг в телеграм). Далі я покажу приклад кастомного Handler класу для надсилання логів у Telegram через бота.

Конфігурація logging

Офіційна документація рекомендує конфігурувати logging через словник python.Для цього необхідно викликати функцію logging.config.dictConfig та передати їй спеціальний словник. Схему словника описано тут. Я лише коротко пробіжуся за основними ключами:

  • version - ключ вказує версію конфіга, рекомендується наявність цього ключа зі значенням 1, потрібно для зворотної сумісності у разі, якщо у майбутньому з'являться нові версії конфігів.
  • disable_existing_loggers - забороняє або дозволяє налаштування для існуючих логерів (на момент запуску), за умовчанням дорівнює True
  • formatters — налаштування форматів логів
  • handlers - налаштування для обробників логів
  • loggers — налаштування існуючих логерів

Раніше всі налаштування я задавав код через виклик методів. Це може бути зручно, якщо у вас один модуль, але коли таких модулів стає безліч, то в кожному з них задавати загальні налаштування здається зайвим заняттям. Давайте спробуємо всі налаштування поставити в одному місці:

import logging.config LOGGING_CONFIG = < 'version': 1, 'disable_existing_loggers': False, 'formatters': < 'default_formatter': < 'format': '[%(levelname)s:%(asctime)s] %(message )s' >, >, 'handlers': < 'stream_handler': < 'class': 'logging.StreamHandler', 'formatter': 'default_formatter', >, >, 'loggers': < 'my_logger': < ' handlers': ['stream_handler'], 'level': 'DEBUG', 'propagate': True >> > logging.config.dictConfig(LOGGING_CONFIG) logger = logging.getLogger('my_logger') logger.debug('debug log')

Чи неправда зручно? У реальних програмах налаштування виносять в окремий модуль, який обов'язково імпортується на старті, наприклад, модуль в settings.py як Django. Саме в ньому задаються глобальні налаштування для всіх логерів програми.

Спадкування у logging

Ще одним зручним механізмом у logging є "успадкування" налаштувань кореневого логера його нащадками. Спадкування задається через символ. у назві логера.Тобто логер під назвою my_package.logger1 успадкує всі налаштування, задані для my_package . Давайте оновимо приклад вище, додавши в LOGGING_CONFIG налаштування для my_package

LOGGING_CONFIG['loggers'].update( < 'my_package': < 'handlers': ['stream_handler'], 'level': 'DEBUG', 'propagate': False >>)

Якщо у вас є налаштування для конкретного логера і ви не хочете, щоб він був додатково оброблений батьківськими Handler класами, ключу propagate потрібно привласнити значення False . У цьому випадку передачу управління "вгору" до батька буде заборонено.

Відправляємо логи в Telegram

А тепер давайте напишемо свій кастомний Handler для надсилання логів через бота в телеграм. Якщо ви ніколи не працювали з телеграм-ботами, почитайте мою статтю про створення телеграм-ботів. Я припускаю, що ви вже створили бота, отримали його токен і знаєте свій user-id/chat-id, щоб бот зміг надсилати повідомлення особисто вам. Для роботи з телеграмом я використовую бібліотеку pyTelegramBotAPI.

Щоб створити свій обробник, необхідно наслідувати клас Handler і перезаписати метод emit :

import telebot from logging import Handler, LogRecord class TelegramBotHandler(Handler): def __init__(self, token: str, chat_id: str): super().__init__() self.token = token self.chat_id = chat_id def emit(self, record: LogRecord): bot = telebot.TeleBot(self.token) bot.send_message( self.chat_id, self.format(record) )

При ініціалізації інстансу класу TelegramBotHandler йому необхідно буде передати токен бота і chat_id. Зазначу, що ці налаштування можна встановити через конфігурування:

'handlers': < 'telegram_handler': < 'class': 'handlers.TelegramBotHandler', 'chat_id': '', 'token': '', 'formatter': 'default_formatter', > >,

Щоб обробник почав свою роботу, достатньо в налаштуваннях вашого логера прописати новий обробник:

LOGGING_CONFIG['loggers'].update( < 'my_package': < 'handlers': ['stream_handler', 'telegram_handler'], 'level': 'DEBUG', 'propagate': False >>)

Висновок

У цій статті я постарався коротко розповісти та показати основні сутності бібліотеки logging, а також продемонструвати гнучкий механізм логування у python. Сподіваюся мені це вдалося, і стаття виявилася для вас корисною.

Цікаві записи:

  • Чому Python?
  • Celery: починаємо правильно
  • Огляд Python 3.9
  • Посібник з роботи з HTTP у Python. Бібліотека requests
  • Робота з MySQL у Python
  • Що нового з'явилося у Django Channels?
  • FastAPI, asyncio і multiprocessing
  • Pyenv: зручний менеджер версій python
  • Django Channels: робота з WebSocket і не тільки
  • Python-RQ: черга завдань на базі Redis
  • Робота з PostgreSQL у Python
  • Введення в pandas: аналіз даних на Python
  • Розгортаємо Django додаток у production на прикладі Telegram бота
  • Як написати Telegram бота: практичний посібник
  • Авторизація через Telegram в Django та Python
  • Django, RQ та FakeRedis
  • Огляд Python 3.8
  • Участь у подкасті TalkPython
  • Будуємо Data Pipeline на Python та Luigi
  • Підсумки першої зустрічі програмістів Python в Алмати
  • Інтеграція Trix editor у Django
  • Авторизація через Telegram в Django додатку
  • Відео презентації ETL на Python

Основи роботи бібліотеки Python Logging

У міру того, як додатки змінюються і ускладнюються, наявність журналу буде корисним при налагодженні і для розуміння проблем, аналізу продуктивності додатків.

Стандартна бібліотека логування в Python поставляється модулем logging, який пропонує більшість головних функцій для ведення лога. При правильному налаштуванні повідомлення лога ми отримаємо багато корисної інформації. Про те, коли і де запускається логування, про контекст лог-журналу, наприклад: запущений процес або потік.

Незважаючи на переваги, модуль logging часто не береться до уваги, так як для правильного налаштування потрібен деякий час. На мій погляд, повна офіційна документація logging насправді не показує кращих методів ведення журналу і не виділяє деякі сюрпризи ведення журналу.

Зауважте, що фрагменти коду в статті припускають, що ви вже імпортували модуль logging:

Концепція Python Logging

У цьому розділі наведено огляд деяких концепцій, які часто зустрічаються в модулі logging.

Python Logging

Рівень лога відповідає його важливості: лог ERROR важливіший, ніж WARNING. Тоді як лог DEBUG слід використовувати лише при налагодженні програми.
Python пропонує шість рівнів лога; кожен рівень пов'язані з числом, що свідчить про важливість лога: NOTSET=0, DEBUG=10, INFO=20, WARNING=30, ERROR=40 і CRITICAL=50.
Ієрархія рівнів інтуїтивно зрозуміла: DEBUG < INFO < WARNING. Крім NOTSET, зі специфікою якого ознайомимося пізніше.

Форматування лога у Python

Форматування лога доповнює повідомлення, додаючи до нього контекстну інформацію. Корисно знати, коли відправляється лог, де (файл Python, номер рядка, метод і т.д.), а також додатковий контекст, такий як потік і процес. Надзвичайно корисні дані при налагодженні багатопотокового додатка.

"%(time)s — %(log_name)s — %(level)s — %(func_name)s:%(line_no)d — %(message)s"
2019-01-16 10:35:12,468 - keyboards - ERROR - module>:1 - привіт світ

Обробник ведення логу в Python

Оброблювач лога — це компонент, який записує та відображає дані лога. Він відображає лог у консолі (через StreamHandler), у файлі (через FileHandler), за допомогою відправки електронного листа (через SMTPHandler) та інших методів.
У кожному обробнику лога 2 важливі поля:

  • Форматувальник, який додає контекстну інформацію в балку.
  • Рівень важливості лога, який фільтрує логи, рівні яких нижче. Тому обробник логу з рівнем INFO не оброблятиме логи DEBUG.

Стандартна бібліотека містить кілька обробників, яких достатньо для більшості випадків: https://docs.python.org/3/library/logging.handlers.html#module-logging.handlers. Найбільш поширені - StreamHandler і FileHandler:

console_handler  = logging.StreamHandler() file_handler  = logging.FileHandler("MyLogFile.txt")

Python Logger

Логгер використовуватиметься найчастіше в коді і буде найскладнішим. Новий Logger отримаємо так:

toto_logger  = logging.getLogger("Privacy")

У логера три основні поля:

  • Propagate: визначає, чи має лог поширюватися на батька журналу. За замовчуванням дорівнює True.
  • Level: як і рівень обробника лога, рівень логера використовується для фільтрації менш важливих логів. З іншого боку, на відміну обробника лога, рівень перевіряється лише з “дітях” логгера; і після того, як ліг поширився серед його батьків, рівень не перевіряться. Це скоріше не інтуїтивна поведінка.
  • Handlers: список обробників, на які відправить балку, коли надійде в Логер. Це робить обробку логів гнучкою, наприклад, ви створите обробник лога для запису у файл, який реєструє логи DEBUG та обробник лога для надсилання електронної пошти, який буде використовуватися тільки для логів CRITICAL. Таким чином, ставлення оброблювача-логгера стає схожим на видавець-споживач: де лог буде передаватися всім оброблювачам після перевірки рівня лога.

Logger визначається по імені, це означає, що якщо створено лог з ім'ям foo , наступні виклики logging.getLogger ("foo") повертатимуть один і той самий об'єкт:

assert
id(logging.getLogger("foo"))
==
id(logging.getLogger("foo"))

Як ви могли здогадатися, у логерів є ієрархія.У верхній частині ієрархії кореневий лог, якого можна отримати доступ через logging.root . Цей лог викликається, коли використовуються методи, як logging.debug() . За замовчуванням рівень кореневого лога — WARNING, тому кожен лог з рівнем нижче ігнорується (наприклад, через logging.info("info") ).
Інша особливість кореневого логгера полягає в тому, що його обробник, за замовчуванням, створюється при першому вході в балку з рівнем вище WARNING.
Використання кореневого логера за допомогою таких методів, як logging.debug() , не рекомендується

lab = logging.getLogger("f.r")
assert lab.parent == logging.root # lab.parent справді кореневий логер

Проте логер використовує “точковий запис”, отже логер з ім'ям f.r буде нащадком логгера f. Однак це справедливо тільки в тому випадку, коли створено лог f, інакше батько fr, як і раніше, буде коренем.

la = logging.getLogger("f")
assert lab.parent == la # Батько lab тепер la замість кореня

Ефективний рівень логера

Коли логгер вирішує, чи лог виводиться відповідно до рівня важливості (наприклад, якщо рівень лога нижче рівня логгера, повідомлення буде проігноровано), він використовує свій “ефективний рівень” замість фактичного рівня.
Ефективний рівень збігається з рівнем логера, якщо рівень не дорівнює NOTSET. Однак, якщо рівень логера дорівнює NOTSET, ефективним рівнем буде перший рівень батька, який не має NOTSET.
За замовчуванням новий логер має рівень NOTSET. Оскільки кореневий логер з рівнем WARNING, ефективний рівень логеру буде WARNING.
Тому навіть якщо новий логер підключений до деяких обробників, ці обробники не будуть викликатися, якщо рівень лога не перевищить WARNING:

foo_logger = logging.getLogger("foo")
assert foo_logger.level == logging.NOTSET # у нового логера рівень NOTSET
assert foo_logger.getEffectiveLevel()
== logging.WARNING # та її ефективний рівень перестав бути рівнем кореневого логгера
# Прикріпіть консольний обробник до foo_logger console_handler = logging.StreamHandler() foo_logger.addHandler(console_handler) foo_logger.debug("debug level")
# нічого не відображається, тому що рівень лога DEBUG менший ніж ефективний рівень foo foo_logger.setLevel(logging.DEBUG) foo_logger.debug("debug message")
# тепер ви побачите на екрані "debug message"

За замовчуванням рівень логера буде використовуватися для рішення про виведення лога. Якщо рівень лога нижче рівня логгера, лог не братиме до уваги.

Рекомендації щодо роботи з Python Logging

Модуль logging дійсно зручний, але зі своїми особливостями, які обертаються годинником головного болю навіть для досвідчених розробників Python. Ось рекомендації щодо використання цього модуля:

  • Налаштуйте кореневий логер, але ніколи не використовуйте його у своєму коді, ніколи не викликайте функцію типу logging.info() , яка залишає кореневий логер без діла. Якщо хочете прибрати повідомлення про помилки з бібліотек, що використовуються, обов'язково налаштуйте кореневий лог для запису у файл, наприклад, щоб полегшити налагодження. За замовчуванням кореневий логер виводить тільки на stderr, тому журнал може легко загубитися.
  • Щоб використовувати логування, створіть новий логгер за допомогою logging.getLogger(ім'я логгера) . Я використовую __name__ як ім'я логгера, але ви можете підібрати інші варіанти. Щоб додати більше одного оброблювача, є метод, який повертає логер.
import logging import sys from logging.handlers import TimedRotatingFileHandler FORMATTER = logging.Formatter("%(time)s - %(name)s - %(level)s - %(message)s") LOG_FILE =
"my_app.log"
def
get_console_handler(): console_handler = logging.StreamHandler(sys.stdout) console_handler.setFormatter(FORMATTER)
return console_handler def
get_file_handler(): file_handler = TimedRotatingFileHandler(LOG_FILE, when='Midnight') file_handler.setFormatter(FORMATTER)
return file_handler def
get_logger(logger_name): logger = logging.getLogger(logger_name) logger.setLevel(logging.DEBUG)
краще мати більше логів, ніж їх брак logger.addHandler(get_console_handler()) logger.addHandler(get_file_handler()) logger.propagate =
False
return logger

Після цього, ви можете створити новий логер і користуватися ним:

my_logger = get_logger("Ім'я модуля наприклад") my_logger.debug("debug повідомлення")
  • Використовуйте класи RotatingFileHandler , такі як TimedRotatingFileHandler , з прикладу замість FileHandler , оскільки він автоматично змінює файл, коли той досягає максимального розміру або робить це щодня.
  • Використовуйте такі інструменти, як Sentry, Airbrake, Raygun і т.д., щоб автоматично ловити повідомлення про помилку. Це корисно під час роботи з додатками. Там лог буває дуже багатослівним, а логи помилок можуть легко загубитися. Іншою перевагою використання цих інструментів це можливість отримати докладну інформацію про значення змінних, які пов'язані з помилкою: яка URL-адреса викликає помилку, який користувач і т.д.

Що таке logging python: повне керівництво з прикладами та порадами

Логування в Python: Логування Python - це процес запису інформації про виконання програми під час її роботи. Це корисний інструмент для налагодження та відстеження проблем у програмах. Python надає вбудований модуль logging для створення та управління логами. Ось деякі основні концепції та приклади використання цього модуля:

import logging # Налаштування логера logging.basicConfig(filename='app.log', level=logging.DEBUG) # Запис повідомлення в лог logging.debug('Це повідомлення налагодження') logging.info('Це інформаційне повідомлення') logging. warning('Це попереджувальне повідомлення') logging.error('Це повідомлення про помилку') logging.critical('Це критичне повідомлення')

У наведеному вище прикладі, ми налаштовуємо логер для запису в файл 'app.log'. Потім ми використовуємо різні рівні логування для запису повідомлень різного типу. відображення лише повідомлень певного рівня або вище. Логи можна використовувати для відстеження виконання програми, виявлення помилок та розуміння того, що відбувається у вашому коді під час виконання.

Детальна відповідь

Що таке логування у Python?

Логування є важливою частиною розробки програмного забезпечення, яка дозволяє записувати та відстежувати інформацію про події та повідомлення, що відбуваються під час виконання програми. , який включає вбудований модуль logging. Цей модуль забезпечує гнучкі засоби для створення та управління логами. додатків.

Як почати використовувати logging у Python?

Для початку використання логування в Python необхідно імпортувати модуль logging:
logger = logging.getLogger(__name__)

Це створить логгер з ім'ям поточного модуля. Ви також маєте можливість призначити рівень логування, щоб вказати, які повідомлення повинні бути записані.Наприклад, можна задати рівень "DEBUG", щоб записати всі повідомлення, включаючи налагоджувальні:

logger.setLevel(logging.DEBUG)

Як записати повідомлення у лог?

Для запису повідомлень в балку, необхідно використовувати різні методи, що надаються логером. Наприклад, можна використовувати методи debug, info, warning, error і critical. Кожен із цих методів записує повідомлення з певним рівнем у балку.

logger.debug("Це повідомлення налагодження") logger.info("Це інформаційне повідомлення") logger.warning("Це попереджувальне повідомлення") logger.error("Це повідомлення про помилку") logger.critical("Це критичне повідомлення" )
Після виконання цього коду кожне повідомлення буде записано в лог із зазначеним рівнем.

Як настроїти форматування логів?

Модуль logging також дозволяє настроювати форматування логів, щоб вони відображалися в зручному для вас вигляді. Для цього можна використати клас Formatter.

formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger.setFormatter(formatter)
Тепер кожне повідомлення, що записується в лог, буде відформатовано відповідно до заданого формату.

Як записувати логи у файл?

Модуль logging дозволяє записувати логи у файли, а не лише виводити їх на консоль. Для цього можна використовувати клас FileHandler.

file_handler = logging.FileHandler('app.log') logger.addHandler(file_handler)

Після створення обробника файлу та додавання його до логера, всі повідомлення будуть записуватись у вказаний файл.

Висновок

У цій статті ми розглянули основи логування Python. Логування – це важливий інструмент для налагодження та відстеження роботи вашої програми. Модуль logging надає потужний інструментарій для створення та управління логами у Python.Ми розглянули, як почати використовувати логування, як записувати повідомлення в лог, налаштувати форматування логів і як записувати логи в файли. Сподіваюся, ця стаття допомогла вам зрозуміти основи логування Python і як застосовувати його у своїх проектах.

Схожі статті

  • Для чого потрібний високочастотний динамік
  • Для чого потрібний DNS у телефоні
  • Для чого потрібний таймер на телефоні
  • Для чого потрібний датчик абсолютного тиску ЗМЗ 406
  • Для чого потрібний мікробіом
  • Для чого потрібний режим гриль у духовці
  • Для чого потрібний Office Tab
  • Для чого потрібний прохідний відігнутий різець
  • Недавні статті

  • Чому взуття скрипить при ходьбі
  • Коли день народження у стрічці
  • Чи можна кішці їсти сіль
  • Варіанти планування ділянки 15 соток прямокутної форми
  • Що означає півмісяця знак
  • Рейсмусовий верстат для чого
  • У якому віці парують свиней
  • У чому полягає принцип нарахування та у яких випадках він застосовується