Запись логов в файл средствами языка Python

Раздел: 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' в явном виде.

- Python log file (логирование в файл в python)
- Python file methods (методы работы с файлами в python)
- File models in python (модели файлов в python)

Продвинутые примеры логирования в файл

Как использовать конфигурацию через словарь?

Модуль 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.

Логирование в файл в Python - comments

En
Python log file (python)