Запись логов в файл средствами языка Python
Основные способы записи логов в файл
Наиболее эффективное и распространенное решение для логирования в файл в Python - использование встроенного модуля logging. Этот модуль предоставляет гибкую систему с уровнями важности, форматированием и возможностью отправки сообщений в разные места (файлы, консоль, сеть). Ниже приведен базовый пример настройки логов в файл с помощью функции basicConfig.
import logging
logging.basicConfig(filename='app.log', level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s')
logging.info('Это информационное сообщение')
logging.warning('Это предупреждение')ввод программ на python (ввод данных в программе python)
После выполнения кода создается файл app.log со следующим содержимым:
2025-03-21 10:15:30,123 - INFO - Это информационное сообщение 2025-03-21 10:15:30,124 - WARNING - Это предупреждение
Python file io (ввод-вывод файлов в python)
Параметр filename указывает путь к файлу. Если файл не существует, он будет создан. Режим по умолчанию - 'a' (дозапись). Уровень level задает минимальный уровень сообщений, которые попадут в лог (в примере - INFO и выше).
Типичная ошибка: забыть установить уровень, и тогда по умолчанию используется WARNING. Сообщения уровня INFO и DEBUG не будут записаны. Решение - всегда явно указывать нужный уровень.
Как настроить различные уровни логирования?
Уровни логирования (DEBUG, INFO, WARNING, ERROR, CRITICAL) позволяют фильтровать сообщения. Настройка выполняется параметром level в basicConfig или при создании логгера.
logging.basicConfig(filename='debug.log', level=logging.DEBUG)
logging.debug('Отладочное сообщение')
logging.info('Информационное сообщение')
Python temp files (временные файлы в python)
Проблема: если установлен уровень DEBUG, в файл попадут все сообщения. Настройка уровня важна для разделения обычной работы и отладки. Ошибка - использовать один уровень для всех случаев, что приводит к захламлению лога или потере важных сообщений.
Как добавить форматирование сообщений?
Строка формата задается через параметр format. Можно включить дату, имя логгера, номер строки и т.д. Пример с временем в формате ISO:
logging.basicConfig(filename='formatted.log', level=logging.WARNING,
format='%(asctime)s [%(levelname)s] %(name)s: %(message)s',
datefmt='%Y-%m-%d %H:%M:%S')
logging.getLogger('my_module').warning('Проверка форматирования')Python index files (индексация файлов в python)
Стандартная ошибка - опечатка в названии атрибута (например, %(messsage)s). Также забывают указать datefmt, если требуется свой формат даты.
Как писать логи в разные файлы?
Для записи в несколько файлов необходимо создать свои логгеры с разными обработчиками (handlers). Каждый логгер может иметь уникальное имя и собственные настройки.
import logging
logger1 = logging.getLogger('app.module1')
h1 = logging.FileHandler('module1.log')
h1.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(name)s - %(levelname)s - %(message)s')
h1.setFormatter(formatter)
logger1.addHandler(h1)
logger2 = logging.getLogger('app.module2')
h2 = logging.FileHandler('module2.log')
h2.setLevel(logging.ERROR)
h2.setFormatter(logging.Formatter('%(asctime)s - %(message)s'))
logger2.addHandler(h2)
logger1.info('Сообщение для module1')
logger2.error('Ошибка для module2')File python class (класс для работы с файлами в python)
Частая проблема - появление дублирующихся сообщений. Это происходит, если логгер наследует обработчики от родительского логгера (propagate=True по умолчанию). Решение - установить logger.propagate = False или настроить корневой логгер.
Как организовать ротацию логов?
Ротация позволяет автоматически создавать новые файлы при достижении определенного размера или по времени. Модуль logging.handlers содержит RotatingFileHandler и TimedRotatingFileHandler.
from logging.handlers import RotatingFileHandler
import logging
handler = RotatingFileHandler('server.log', maxBytes=1024, backupCount=3)
handler.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(message)s')
handler.setFormatter(formatter)
logger = logging.getLogger('server')
logger.addHandler(handler)
logger.setLevel(logging.INFO)
for i in range(10):
logger.info(f'Сообщение номер {i}')Python file utf 8 (кодировка utf-8 для файлов в python)
После заполнения файла до 1024 байт создается новый файл server.log.1, а старые сдвигаются. backupCount=3 означает хранение трех резервных копий.
Ошибка: не указать backupCount, тогда резервные копии не будут удаляться, и диск может переполниться. Также важно не забывать задавать mode='a' (добавление), иначе при запуске файл будет перезаписан.
Как указать кодировку файла?
По умолчанию FileHandler использует кодировку, заданную в системе, что может привести к проблемам с символами (например, кириллицей в Windows). Явное указание encoding='utf-8' решает эту проблему.
handler = logging.FileHandler('utf8.log', encoding='utf-8')
logging.basicConfig(handlers=[handler], level=logging.INFO)
logging.info('Русский текст: привет!')Если не указать кодировку, в Windows может использоваться cp1251, и при чтении файла в редакторе с UTF-8 символы отобразятся некорректно. Рекомендуется всегда задавать encoding='utf-8' в явном виде.
Продвинутые примеры логирования в файл
Как использовать конфигурацию через словарь?
Модуль logging.config позволяет задать настройки с помощью словаря или конфигурационного файла. Это удобно для больших проектов.
import logging.config
config = {
'version': 1,
'handlers': {
'file': {
'class': 'logging.FileHandler',
'filename': 'dict_config.log',
'formatter': 'simple'
}
},
'formatters': {
'simple': {
'format': '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
}
},
'root': {
'level': 'INFO',
'handlers': ['file']
}
}
logging.config.dictConfig(config)
logging.info('Логирование настроено через словарь')2025-03-21 10:15:30,123 - root - INFO - Логирование настроено через словарь
Конфигурация через словарь позволяет гибко управлять логгерами, форматтерами и фильтрами без изменения кода.
Как логировать исключения с полным traceback?
Для записи стека вызова при исключении используется метод exception или параметр exc_info=True.
import logging
logging.basicConfig(filename='errors.log', level=ERROR)
try:
1/0
except ZeroDivisionError:
logging.exception('Произошла ошибка деления на ноль')ERROR - Произошла ошибка деления на ноль Traceback (most recent call last): File "<stdin>", line 2, in <module> ZeroDivisionError: division by zero
Метод exception автоматически добавляет traceback. Важно: он работает только внутри блока except.
Как применить фильтры для выборочного логирования?
Фильтры позволяют контролировать, какие сообщения попадают в файл. Например, можно отфильтровать сообщения от определенного модуля.
import logging
class ModuleFilter(logging.Filter):
def filter(self, record):
return record.name.startswith('important')
handler = logging.FileHandler('filtered.log')
handler.addFilter(ModuleFilter())
logger = logging.getLogger('important.module')
logger.addHandler(handler)
logger.setLevel(logging.DEBUG)
logger.info('Это сообщение будет записано')
logging.getLogger('other').info('Это сообщение не будет')Содержимое filtered.log: 2025-03-21 10:15:30,123 - important.module - INFO - Это сообщение будет записано
Фильтры добавляются к обработчику или логгеру. В примере записываются только сообщения от логгеров, имя которых начинается с 'important'.
Как организовать асинхронное логирование в файл?
При высоконагруженных приложениях запись логов может стать узким местом. Асинхронное логирование с использованием QueueHandler и QueueListener решает эту проблему.
import logging
import logging.handlers
from queue import Queue
log_queue = Queue(-1)
queue_handler = logging.handlers.QueueHandler(log_queue)
file_handler = logging.FileHandler('async.log')
file_handler.setFormatter(logging.Formatter('%(asctime)s - %(message)s'))
listener = logging.handlers.QueueListener(log_queue, file_handler, respect_handler_level=True)
listener.start()
logger = logging.getLogger('async')
logger.addHandler(queue_handler)
logger.setLevel(logging.INFO)
logger.info('Асинхронное сообщение 1')
logger.info('Асинхронное сообщение 2')
listener.stop()Логи отправляются в очередь, а отдельный поток извлекает их и записывает в файл. Это снижает задержки в основном потоке. Важно не забыть остановить слушатель после завершения работы.
Как сохранять логи в формате JSON?
Для интеграции с системами анализа логов (например, ELK) удобно хранить сообщения в JSON. Для этого используется сторонняя библиотека python-json-logger.
from pythonjsonlogger import jsonlogger
import logging
handler = logging.FileHandler('app.json')
formatter = jsonlogger.JsonFormatter('%(asctime)s %(levelname)s %(name)s %(message)s')
handler.setFormatter(formatter)
logger = logging.getLogger('json_example')
logger.addHandler(handler)
logger.setLevel(logging.DEBUG)
logger.info('Тестовое сообщение', extra={'user': 'admin', 'process_id': 123}){"asctime": "2025-03-21 10:15:30,123", "levelname": "INFO", "name": "json_example", "message": "Тестовое сообщение", "user": "admin", "process_id": 123}Каждое сообщение превращается в JSON-объект, что упрощает парсинг. Библиотека устанавливается командой pip install python-json-logger.