> **Источник:** https://python-all.ru/3.15/library/logging.handlers.html
>
> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.

---

# `logging.handlers` – Обработчики логирования

**Исходный код:** [Lib/logging/handlers.py](https://python-all.ru/src/3.15/Lib/logging/handlers.py)

Важно

На этой странице представлена только справочная информация. Учебные руководства см. в

- [Базовое руководство](https://python-all.ru/3.15/howto/logging.html#logging-basic-tutorial)
- [Продвинутое руководство](https://python-all.ru/3.15/howto/logging.html#logging-advanced-tutorial)
- [Поваренная книга по логированию](https://python-all.ru/3.15/howto/logging-cookbook.html#logging-cookbook)

---

В пакете представлены следующие полезные обработчики. Обратите внимание, что три из них ([`StreamHandler`](https://python-all.ru/3.15/library/logging.handlers.html#logging.StreamHandler), [`FileHandler`](https://python-all.ru/3.15/library/logging.handlers.html#logging.FileHandler) и [`NullHandler`](https://python-all.ru/3.15/library/logging.handlers.html#logging.NullHandler)) на самом деле определены в самом модуле [`logging`](https://python-all.ru/3.15/library/logging.html#module-logging), но документированы здесь вместе с остальными обработчиками.

## StreamHandler

Класс [`StreamHandler`](https://python-all.ru/3.15/library/logging.handlers.html#logging.StreamHandler), находящийся в основном пакете [`logging`](https://python-all.ru/3.15/library/logging.html#module-logging), отправляет вывод логирования в потоки данных, такие как *sys.stdout*, *sys.stderr* или любой объект, похожий на файл (или, точнее, любой объект, который поддерживает методы `write()` и `flush()`).

#### `class logging.StreamHandler(stream=None)`

Возвращает новый экземпляр класса `StreamHandler`. Если указан *stream*, экземпляр будет использовать его для вывода логирования; в противном случае будет использоваться *sys.stderr*.

#### `emit(record)`

Если указан форматтер, он используется для форматирования записи. Затем запись записывается в поток данных, за которым следует [`terminator`](https://python-all.ru/3.15/library/logging.handlers.html#logging.StreamHandler.terminator). Если присутствует информация об исключении, она форматируется с помощью [`traceback.print_exception()`](https://python-all.ru/3.15/library/traceback.html#traceback.print_exception) и добавляется в поток.

#### `flush()`

Сбрасывает поток данных вызовом его метода `flush()`. Обратите внимание, что метод `close()` наследуется от [`Handler`](https://python-all.ru/3.15/library/logging.html#logging.Handler) и поэтому не производит вывода, так что иногда может потребоваться явный вызов `flush()`.

#### `setStream(stream)`

Устанавливает поток данных экземпляра на указанное значение, если оно отличается. Старый поток данных сбрасывается перед установкой нового.

**Параметры:**

**stream** – Поток данных, который должен использовать обработчик.

**Возвращает:**

старый поток, если поток был изменён, или `None`, если нет.

Добавлено в версии 3.7.

#### `terminator`

Строка, используемая как терминатор при записи форматированной записи в поток. Значение по умолчанию – `'\n'`.

Если завершающий перевод строки не нужен, можно установить атрибут `terminator` экземпляра обработчика в пустую строку.

В более ранних версиях терминатор был жёстко задан как `'\n'`.

Добавлено в версии 3.2.

## FileHandler

Класс [`FileHandler`](https://python-all.ru/3.15/library/logging.handlers.html#logging.FileHandler), находящийся в основном пакете [`logging`](https://python-all.ru/3.15/library/logging.html#module-logging), направляет вывод журнала в файл на диске. Он наследует функциональность вывода от [`StreamHandler`](https://python-all.ru/3.15/library/logging.handlers.html#logging.StreamHandler).

#### `class logging.FileHandler(filename, mode='a', encoding=None, delay=False, errors=None)`

Возвращает новый экземпляр класса `FileHandler`. Указанный файл открывается и используется как поток для журналирования. Если *mode* не указан, используется `'a'`. Если *encoding* не равен `None`, файл открывается с указанной кодировкой. Если *delay* равен true, открытие файла откладывается до первого вызова [`emit()`](https://python-all.ru/3.15/library/logging.handlers.html#logging.FileHandler.emit). По умолчанию файл растёт бесконечно. Если указан *errors*, он определяет, как обрабатываются ошибки кодировки.

Изменено в версии 3.6: Помимо строковых значений, для аргумента *filename* теперь принимаются также объекты [`Path`](https://python-all.ru/3.15/library/pathlib.html#pathlib.Path).

Изменено в версии 3.9: Добавлен параметр *errors*.

#### `close()`

Закрывает файл.

#### `emit(record)`

Выводит запись в файл.

Обратите внимание: если файл был закрыт из-за завершения работы журналирования при выходе, а режим файла – ‘w’, запись не будет выведена (см. [bpo-42378](https://python-all.ru/3.15/library/logging.handlers.html)).

## NullHandler

Добавлено в версии 3.1.

Класс [`NullHandler`](https://python-all.ru/3.15/library/logging.handlers.html#logging.NullHandler), находящийся в основном пакете [`logging`](https://python-all.ru/3.15/library/logging.html#module-logging), не выполняет никакого форматирования или вывода. По сути это обработчик-пустышка (‘no-op’), предназначенный для разработчиков библиотек.

#### `class logging.NullHandler`

Возвращает новый экземпляр класса `NullHandler`.

#### `emit(record)`

Этот метод ничего не делает.

#### `handle(record)`

Этот метод ничего не делает.

#### `createLock()`

Этот метод возвращает `None` для блокировки, так как нет базового ввода-вывода, доступ к которому нужно сериализовать.

См. [Настройка журналирования для библиотеки](https://python-all.ru/3.15/howto/logging.html#library-config) для получения дополнительной информации об использовании [`NullHandler`](https://python-all.ru/3.15/library/logging.handlers.html#logging.NullHandler).

## WatchedFileHandler

Класс [`WatchedFileHandler`](https://python-all.ru/3.15/library/logging.handlers.html#logging.handlers.WatchedFileHandler), находящийся в модуле `logging.handlers`, представляет собой `FileHandler`, который отслеживает файл, в который ведётся журналирование. Если файл изменяется, он закрывается и снова открывается по тому же имени.

Файл может измениться из-за использования таких программ, как *newsyslog* и *logrotate*, которые выполняют ротацию файлов журнала. Этот обработчик, предназначенный для использования в Unix/Linux, следит, не изменился ли файл с момента последнего вызова emit. (Считается, что файл изменился, если изменились его устройство или inode.) Если файл изменился, старый поток файла закрывается, а файл открывается для получения нового потока.

Этот обработчик не подходит для использования в Windows, потому что в Windows открытые файлы журнала нельзя перемещать или переименовывать – журналирование открывает файлы с эксклюзивными блокировками, – поэтому такой обработчик не нужен. Кроме того, *ST\_INO* не поддерживается в Windows; [`stat()`](https://python-all.ru/3.15/library/os.html#os.stat) всегда возвращает ноль для этого значения.

#### `class logging.handlers.WatchedFileHandler(filename, mode='a', encoding=None, delay=False, errors=None)`

Возвращает новый экземпляр класса `WatchedFileHandler`. Указанный файл открывается и используется как поток для логирования. Если *mode* не указан, используется `'a'`. Если *encoding* не равен `None`, он используется для открытия файла с этой кодировкой. Если *delay* равен true, открытие файла откладывается до первого вызова [`emit()`](https://python-all.ru/3.15/library/logging.handlers.html#logging.handlers.WatchedFileHandler.emit). По умолчанию файл растёт бесконечно. Если указан *errors*, он определяет, как обрабатываются ошибки кодирования.

Изменено в версии 3.6: Помимо строковых значений, для аргумента *filename* теперь принимаются также объекты [`Path`](https://python-all.ru/3.15/library/pathlib.html#pathlib.Path).

Изменено в версии 3.9: Добавлен параметр *errors*.

#### `reopenIfNeeded()`

Проверяет, изменился ли файл. Если изменился, существующий поток данных сбрасывается и закрывается, а файл открывается заново, обычно перед выводом записи в файл.

Добавлено в версии 3.6.

#### `emit(record)`

Выводит запись в файл, но сначала вызывает [`reopenIfNeeded()`](https://python-all.ru/3.15/library/logging.handlers.html#logging.handlers.WatchedFileHandler.reopenIfNeeded), чтобы переоткрыть файл, если он изменился.

## BaseRotatingHandler

Класс [`BaseRotatingHandler`](https://python-all.ru/3.15/library/logging.handlers.html#logging.handlers.BaseRotatingHandler), находящийся в модуле `logging.handlers`, является базовым классом для ротируемых файловых обработчиков [`RotatingFileHandler`](https://python-all.ru/3.15/library/logging.handlers.html#logging.handlers.RotatingFileHandler) и [`TimedRotatingFileHandler`](https://python-all.ru/3.15/library/logging.handlers.html#logging.handlers.TimedRotatingFileHandler). Обычно не требуется создавать экземпляр этого класса, но у него есть атрибуты и методы, которые может потребоваться переопределить.

#### `class logging.handlers.BaseRotatingHandler(filename, mode, encoding=None, delay=False, errors=None)`

Параметры такие же, как для `FileHandler`. Атрибуты:

#### `namer`

Если этому атрибуту присвоен вызываемый объект, метод [`rotation_filename()`](https://python-all.ru/3.15/library/logging.handlers.html#logging.handlers.BaseRotatingHandler.rotation_filename) делегирует вызов этому объекту. Параметры, передаваемые вызываемому объекту, такие же, как у `rotation_filename()`.

> **Примечание**
>
> Функция namer вызывается довольно много раз во время ротации, поэтому она должна быть максимально простой и быстрой. Она также должна возвращать одинаковый результат для одного и того же входного значения, иначе поведение ротации может не соответствовать ожидаемому.
>
> Также стоит отметить, что при использовании namer следует соблюдать осторожность, чтобы сохранить определённые атрибуты в имени файла, которые используются во время ротации. Например, [`RotatingFileHandler`](https://python-all.ru/3.15/library/logging.handlers.html#logging.handlers.RotatingFileHandler) ожидает набор файлов журнала, чьи имена содержат последовательные целые числа, чтобы ротация работала как ожидается, а [`TimedRotatingFileHandler`](https://python-all.ru/3.15/library/logging.handlers.html#logging.handlers.TimedRotatingFileHandler) удаляет старые файлы журнала (на основе параметра `backupCount`, переданного инициализатору обработчика), определяя самые старые файлы для удаления. Для этого имена файлов должны быть сортируемы по части даты/времени, и namer должен это учитывать. (Если нужен namer, который не соблюдает эту схему, его следует использовать в подклассе `TimedRotatingFileHandler`, переопределяющем метод [`getFilesToDelete()`](https://python-all.ru/3.15/library/logging.handlers.html#logging.handlers.TimedRotatingFileHandler.getFilesToDelete), чтобы соответствовать пользовательской схеме именования.)

Добавлено в версии 3.3.

#### `rotator`

Если этому атрибуту присвоен вызываемый объект, метод [`rotate()`](https://python-all.ru/3.15/library/logging.handlers.html#logging.handlers.BaseRotatingHandler.rotate) делегирует вызов этому объекту. Параметры, передаваемые вызываемому объекту, такие же, как у `rotate()`.

Добавлено в версии 3.3.

#### `rotation_filename(default_name)`

Изменяет имя файла журнала при ротации.

Это предусмотрено, чтобы можно было задать пользовательское имя файла.

Реализация по умолчанию вызывает атрибут ‘namer’ обработчика, если он вызываем, передавая ему имя по умолчанию. Если атрибут не является вызываемым (по умолчанию `None`), имя возвращается без изменений.

**Параметры:**

**default\_name** – имя файла журнала по умолчанию.

Добавлено в версии 3.3.

#### `rotate(source, dest)`

При ротации выполняет ротацию текущего журнала.

Реализация по умолчанию вызывает атрибут ‘rotator’ обработчика, если он вызываем, передавая ему аргументы source и dest. Если атрибут не вызываем (по умолчанию `None`), source просто переименовывается в destination.

**Параметры:**

- **source** – исходное имя файла. Обычно это базовое имя файла, например ‘test.log’.
- **dest** – имя файла назначения. Обычно это то, во что ротируется source, например ‘test.log.1’.

Добавлено в версии 3.3.

Атрибуты существуют, чтобы избавить от необходимости создавать подклассы – можно использовать одни и те же вызываемые объекты для экземпляров [`RotatingFileHandler`](https://python-all.ru/3.15/library/logging.handlers.html#logging.handlers.RotatingFileHandler) и [`TimedRotatingFileHandler`](https://python-all.ru/3.15/library/logging.handlers.html#logging.handlers.TimedRotatingFileHandler). Если какой-либо из вызываемых объектов namer или rotator вызывает исключение, оно обрабатывается так же, как и любое другое исключение во время вызова `emit()`, то есть через метод `handleError()` обработчика.

Если требуется внести более существенные изменения в обработку ротации, можно переопределить методы.

Пример см. в [Использование rotator и namer для настройки обработки ротации журналов](https://python-all.ru/3.15/howto/logging-cookbook.html#cookbook-rotator-namer).

## RotatingFileHandler

Класс [`RotatingFileHandler`](https://python-all.ru/3.15/library/logging.handlers.html#logging.handlers.RotatingFileHandler), находящийся в модуле `logging.handlers`, поддерживает ротацию файлов журнала на диске.

#### `class logging.handlers.RotatingFileHandler(filename, mode='a', maxBytes=0, backupCount=0, encoding=None, delay=False, errors=None)`

Возвращает новый экземпляр класса `RotatingFileHandler`. Указанный файл открывается и используется как поток для логирования. Если *mode* не указан, используется `'a'`. Если *encoding* не равен `None`, он используется для открытия файла с этой кодировкой. Если *delay* равен true, открытие файла откладывается до первого вызова [`emit()`](https://python-all.ru/3.15/library/logging.handlers.html#logging.handlers.RotatingFileHandler.emit). По умолчанию файл растёт бесконечно. Если указан *errors*, он определяет, как обрабатываются ошибки кодирования.

Значения *maxBytes* и *backupCount* позволяют задать *ротацию (rollover)* файла по достижении заданного размера. Когда размер вот-вот будет превышен, файл закрывается и новый файл незаметно открывается для записи. Ротация происходит каждый раз, когда текущий файл журнала почти достигает длины *maxBytes*; но если *maxBytes* или *backupCount* равно нулю, ротация не выполняется, поэтому обычно рекомендуется установить *backupCount* не менее 1, а *maxBytes* – ненулевым. Когда *backupCount* не равен нулю, система сохраняет старые файлы журнала, добавляя к имени файла расширения '.1', '.2' и т. д. Например, при *backupCount*, равном 5, и базовом имени файла `app.log`, вы получите файлы `app.log`, `app.log.1`, `app.log.2`, вплоть до `app.log.5`. Файл, в который ведётся запись, всегда `app.log`. Когда этот файл заполняется, он закрывается и переименовывается в `app.log.1`, а если существуют файлы `app.log.1`, `app.log.2` и т. д., то они переименовываются соответственно в `app.log.2`, `app.log.3` и т. д.

Изменено в версии 3.6: Помимо строковых значений, для аргумента *filename* теперь принимаются также объекты [`Path`](https://python-all.ru/3.15/library/pathlib.html#pathlib.Path).

Изменено в версии 3.9: Добавлен параметр *errors*.

#### `doRollover()`

Выполняет ротацию, как описано выше.

#### `emit(record)`

Записывает запись (record) в файл, выполняя при необходимости ротацию, как описано ранее.

#### `shouldRollover(record)`

Определяет, приведёт ли переданная запись (record) к превышению заданного ограничения размера файла.

## TimedRotatingFileHandler

Класс [`TimedRotatingFileHandler`](https://python-all.ru/3.15/library/logging.handlers.html#logging.handlers.TimedRotatingFileHandler), расположенный в модуле `logging.handlers`, поддерживает ротацию файлов журнала на диске через заданные временные интервалы.

#### `class logging.handlers.TimedRotatingFileHandler(filename, when='h', interval=1, backupCount=0, encoding=None, delay=False, utc=False, atTime=None, errors=None)`

Возвращает новый экземпляр класса `TimedRotatingFileHandler`. Указанный файл открывается и используется как поток для логирования. При ротации также устанавливается суффикс имени файла. Ротация происходит на основе произведения *when* и *interval*.

Параметр *when* указывает тип *interval*. Список возможных значений приведён ниже. Обратите внимание, что регистр не учитывается.

| Значение | Тип интервала | Используется ли *atTime* и как |
| --- | --- | --- |
| `'S'` | Секунды | Игнорируется |
| `'M'` | Минуты | Игнорируется |
| `'H'` | Часы | Игнорируется |
| `'D'` | Дни | Игнорируется |
| `'W0'-'W6'` | День недели (0=понедельник) | Используется для вычисления начального времени ротации |
| `'midnight'` | Ротация в полночь, если *atTime* не указан, иначе в момент времени *atTime* | Используется для вычисления начального времени ротации |

При использовании ротации по дням недели укажите 'W0' для понедельника, 'W1' для вторника и так далее до 'W6' для воскресенья. В этом случае значение, переданное для *interval*, не используется.

Система сохраняет старые файлы журнала, добавляя расширения к имени файла. Расширения основаны на дате и времени с использованием формата strftime `%Y-%m-%d_%H-%M-%S` или его начальной части в зависимости от интервала ротации.

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

Если аргумент *utc* равен true, используется время в UTC; в противном случае используется местное время.

Если *backupCount* не равен нулю, сохраняется не более *backupCount* файлов; если при ротации должно быть создано больше файлов, самый старый удаляется. Логика удаления использует интервал для определения того, какие файлы нужно удалить, поэтому изменение интервала может привести к тому, что старые файлы останутся.

Если *delay* равен true, открытие файла откладывается до первого вызова [`emit()`](https://python-all.ru/3.15/library/logging.handlers.html#logging.handlers.TimedRotatingFileHandler.emit).

Если *atTime* не равен `None`, он должен быть экземпляром `datetime.time`, который задаёт время суток для ротации в случаях, когда ротация должна происходить «в полночь» или «в определённый день недели». Обратите внимание, что в этих случаях значение *atTime* фактически используется для вычисления *первой* ротации, а последующие ротации рассчитываются обычным образом по интервалу.

Если указан параметр *errors*, он определяет, как обрабатываются ошибки кодирования.

> **Примечание**
>
> Расчёт времени первой ротации выполняется при инициализации обработчика. Расчёт последующих ротаций выполняется только при наступлении ротации, а ротация происходит только при выводе записи. Если это не учитывать, может возникнуть путаница. Например, если задан интервал «каждую минуту», это не означает, что временные метки в именах файлов всегда будут отличаться ровно на минуту; если во время выполнения приложения записи журнала генерируются чаще, чем раз в минуту, *то* можно ожидать, что временные метки файлов будут разделены минутой. Если же записи журнала выводятся только раз в пять минут (скажем), то в именах файлов будут пропуски, соответствующие минутам, когда не было вывода (и, следовательно, ротации).

Изменено в версии 3.4: Добавлен параметр *atTime*.

Изменено в версии 3.6: Помимо строковых значений, для аргумента *filename* теперь принимаются также объекты [`Path`](https://python-all.ru/3.15/library/pathlib.html#pathlib.Path).

Изменено в версии 3.9: Добавлен параметр *errors*.

#### `doRollover()`

Выполняет ротацию, как описано выше.

#### `emit(record)`

Выводит запись в файл, обеспечивая ротацию, как описано выше.

#### `getFilesToDelete()`

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

#### `shouldRollover(record)`

Проверяет, прошло ли достаточно времени для ротации, и если да, вычисляет время следующей ротации.

## SocketHandler

Класс [`SocketHandler`](https://python-all.ru/3.15/library/logging.handlers.html#logging.handlers.SocketHandler), находящийся в модуле `logging.handlers`, отправляет вывод журнала в сетевой сокет. Базовый класс использует TCP-сокет.

#### `class logging.handlers.SocketHandler(host, port)`

Возвращает новый экземпляр класса `SocketHandler`, предназначенный для обмена данными с удалённой машиной, адрес которой задаётся параметрами *host* и *port*.

Изменено в версии 3.4: Если `port` указан как `None`, создаётся сокет домена Unix с использованием значения `host`; в противном случае создаётся TCP-сокет.

#### `close()`

Закрывает сокет.

#### `emit()`

Сериализует словарь атрибутов записи с помощью модуля pickle и записывает его в сокет в двоичном формате. При ошибке сокета пакет молча отбрасывается. Если соединение было потеряно, оно восстанавливается. Для десериализации записи на принимающей стороне в [`LogRecord`](https://python-all.ru/3.15/library/logging.html#logging.LogRecord) используйте функцию [`makeLogRecord()`](https://python-all.ru/3.15/library/logging.html#logging.makeLogRecord).

#### `handleError()`

Обрабатывает ошибку, возникшую во время [`emit()`](https://python-all.ru/3.15/library/logging.handlers.html#logging.handlers.SocketHandler.emit). Наиболее вероятная причина – потеря соединения. Закрывает сокет, чтобы повторить попытку при следующем событии.

#### `makeSocket()`

Это фабричный метод, который позволяет подклассам задать точный тип сокета. Реализация по умолчанию создаёт TCP-сокет ([`socket.SOCK_STREAM`](https://python-all.ru/3.15/library/socket.html#socket.SOCK_STREAM)).

#### `makePickle(record)`

Сериализует словарь атрибутов записи с помощью модуля pickle в двоичном формате с префиксом длины и возвращает его, готовым к отправке через сокет. Подробности этой операции эквивалентны следующему:

```python
data = pickle.dumps(record_attr_dict, 1)
datalen = struct.pack('>L', len(data))
return datalen + data
```

Обратите внимание, что модуль pickle не является полностью безопасным. Если вас беспокоит безопасность, вы можете переопределить этот метод, чтобы реализовать более надёжный механизм. Например, можно подписывать данные с помощью HMAC и проверять подпись на принимающей стороне, либо отключить десериализацию глобальных объектов на принимающей стороне.

#### `send(packet)`

Отправляет сериализованную байтовую строку *пакет* в сокет. Формат отправляемой байтовой строки описан в документации [`makePickle()`](https://python-all.ru/3.15/library/logging.handlers.html#logging.handlers.SocketHandler.makePickle).

Эта функция допускает частичную отправку, что может произойти при загруженности сети.

#### `createSocket()`

Пытается создать сокет; в случае неудачи применяет алгоритм экспоненциальной отсрочки. При первой неудаче обработчик отбрасывает сообщение, которое пытался отправить. Когда последующие сообщения обрабатываются тем же экземпляром, он не будет пытаться установить соединение, пока не пройдёт некоторое время. Значения параметров по умолчанию таковы, что начальная задержка составляет одну секунду, и если после этой задержки соединение всё ещё не может быть установлено, обработчик будет удваивать задержку каждый раз вплоть до максимума в 30 секунд.

Это поведение управляется следующими атрибутами обработчика:

- `retryStart` (начальная задержка, по умолчанию 1,0 секунды).
- `retryFactor` (множитель, по умолчанию 2.0).
- `retryMax` (максимальная задержка, по умолчанию 30,0 секунд).

Это означает, что если удалённый слушатель запускается *после* того, как обработчик уже использовался, возможна потеря сообщений (поскольку обработчик даже не будет пытаться установить соединение, пока не истечёт задержка, а будет просто молча отбрасывать сообщения в течение этого периода).

## DatagramHandler

Класс [`DatagramHandler`](https://python-all.ru/3.15/library/logging.handlers.html#logging.handlers.DatagramHandler), находящийся в модуле `logging.handlers`, наследует от [`SocketHandler`](https://python-all.ru/3.15/library/logging.handlers.html#logging.handlers.SocketHandler) для поддержки отправки сообщений журнала через UDP-сокеты.

#### `class logging.handlers.DatagramHandler(host, port)`

Возвращает новый экземпляр класса `DatagramHandler`, предназначенный для обмена данными с удалённой машиной, адрес которой задаётся параметрами *host* и *port*.

> **Примечание**
>
> Поскольку UDP не является потоковым протоколом, постоянное соединение между экземпляром этого обработчика и *host* отсутствует. По этой причине при использовании сетевого сокета каждый раз при логировании события может потребоваться DNS-запрос, что может привести к некоторой задержке в системе. Если это создаёт проблемы, можно выполнить запрос самостоятельно и инициализировать этот обработчик, используя полученный IP-адрес вместо имени узла.

Изменено в версии 3.4: Если `port` задан как `None`, создаётся доменный сокет Unix с использованием значения `host`; в противном случае создаётся UDP-сокет.

#### `emit()`

Сериализует словарь атрибутов записи и записывает его в сокет в двоичном формате. В случае ошибки сокета молча отбрасывает пакет. Чтобы десериализовать запись на принимающей стороне в объект [`LogRecord`](https://python-all.ru/3.15/library/logging.html#logging.LogRecord), используйте функцию [`makeLogRecord()`](https://python-all.ru/3.15/library/logging.html#logging.makeLogRecord).

#### `makeSocket()`

Фабричный метод [`SocketHandler`](https://python-all.ru/3.15/library/logging.handlers.html#logging.handlers.SocketHandler) здесь переопределён для создания UDP-сокета ([`socket.SOCK_DGRAM`](https://python-all.ru/3.15/library/socket.html#socket.SOCK_DGRAM)).

#### `send(s)`

Отправляет сериализованную (pickled) байтовую строку в сокет. Формат отправляемой байтовой строки описан в документации [`SocketHandler.makePickle()`](https://python-all.ru/3.15/library/logging.handlers.html#logging.handlers.SocketHandler.makePickle).

## SysLogHandler

Класс [`SysLogHandler`](https://python-all.ru/3.15/library/logging.handlers.html#logging.handlers.SysLogHandler), находящийся в модуле `logging.handlers`, поддерживает отправку сообщений журнала в удалённый или локальный системный журнал Unix (syslog).

#### `class logging.handlers.SysLogHandler(address=('localhost', SYSLOG_UDP_PORT), facility=LOG_USER, socktype=socket.SOCK_DGRAM, timeout=None)`

Возвращает новый экземпляр класса `SysLogHandler`, предназначенный для связи с удалённой Unix-машиной, адрес которой задаётся *address* в виде кортежа `(host, port)`. Если *address* не указан, используется `('localhost', 514)`. Адрес используется для открытия сокета. Вместо кортежа `(host, port)` можно указать адрес в виде строки, например '/dev/log'. В этом случае для отправки сообщения в syslog используется доменный сокет Unix. Если *facility* не указан, используется `LOG_USER`. Тип открываемого сокета зависит от аргумента *socktype*, который по умолчанию равен [`socket.SOCK_DGRAM`](https://python-all.ru/3.15/library/socket.html#socket.SOCK_DGRAM) и, таким образом, открывает UDP-сокет. Чтобы открыть TCP-сокет (для использования с новыми демонами syslog, такими как rsyslog), укажите значение [`socket.SOCK_STREAM`](https://python-all.ru/3.15/library/socket.html#socket.SOCK_STREAM). Если указан *timeout*, он задаёт тайм-аут (в секундах) для операций с сокетом. Это может помочь предотвратить бесконечное зависание программы, если сервер syslog недоступен. По умолчанию *timeout* равен `None`, то есть тайм-аут не применяется.

Обратите внимание: если ваш сервер не прослушивает UDP-порт 514, `SysLogHandler` может не работать. В этом случае проверьте, какой адрес следует использовать для доменного сокета – это зависит от системы. Например, в Linux это обычно '/dev/log', а в OS/X – '/var/run/syslog'. Необходимо проверить вашу платформу и использовать соответствующий адрес (возможно, потребуется выполнять эту проверку во время выполнения, если приложение должно работать на нескольких платформах). В Windows практически всегда приходится использовать UDP.

> **Примечание**
>
> В macOS 12.x (Monterey) компания Apple изменила поведение своего демона syslog – он больше не прослушивает доменный сокет. Поэтому не стоит рассчитывать на работу `SysLogHandler` в этой системе.
>
> См. [gh-91070](https://python-all.ru/3.15/library/logging.handlers.html) для получения дополнительной информации.

Изменено в версии 3.2: добавлен параметр *socktype*.

Изменено в версии 3.14: добавлен параметр *timeout*.

#### `close()`

Закрывает сокет, подключённый к удалённому узлу.

#### `createSocket()`

Пытается создать сокет и, если это не дейтаграммный сокет, подключить его к другому концу. Этот метод вызывается во время инициализации обработчика, но это не считается ошибкой, если другой конец в этот момент не прослушивается – метод будет вызван снова при отправке события, если сокет на тот момент отсутствует.

Добавлено в версии 3.12.

#### `emit(record)`

Запись форматируется и отправляется на сервер syslog. Если присутствует информация об исключении, она *не* отправляется на сервер.

Изменено в версии 3.2.1: (См.: [bpo-12168](https://python-all.ru/3.15/library/logging.handlers.html).) В более ранних версиях сообщение, отправляемое демонам syslog, всегда завершалось нулевым байтом (NUL), поскольку ранние версии этих демонов ожидали сообщение, завершённое нулём, – хотя в соответствующей спецификации ([**RFC 5424**](https://python-all.ru/3.15/library/logging.handlers.html)) этого нет. Более новые версии этих демонов не ожидают нулевой байт, но отбрасывают его, если он присутствует, а ещё более новые демоны (которые строже следуют RFC 5424) передают нулевой байт как часть сообщения.

Чтобы упростить обработку сообщений syslog в условиях такого различного поведения демонов, добавление нулевого байта было сделано настраиваемым с помощью атрибута уровня класса, `append_nul`. По умолчанию он равен `True` (сохраняя существующее поведение), но может быть установлен в `False` на экземпляре `SysLogHandler`, чтобы этот экземпляр *не* добавлял нулевой терминатор.

Изменено в версии 3.3: (См.: [bpo-12419](https://python-all.ru/3.15/library/logging.handlers.html).) В более ранних версиях не было возможности указать префикс «ident» или «tag» для идентификации источника сообщения. Теперь это можно задать с помощью атрибута уровня класса, по умолчанию равного `""` для сохранения существующего поведения, но который может быть переопределён на экземпляре `SysLogHandler`, чтобы этот экземпляр добавлял идентификатор к каждому обработанному сообщению. Обратите внимание, что указанный идентификатор должен быть текстом, а не байтами, и добавляется к сообщению без изменений.

#### `encodePriority(facility, priority)`

Кодирует средство и приоритет в целое число. Можно передавать строки или целые числа – если передаются строки, внутренние словари сопоставлений используются для преобразования их в целые числа.

Символические значения `LOG_` определены в `SysLogHandler` и отражают значения, определённые в заголовочном файле `sys/syslog.h`.

**Приоритеты**

| Имя (строка) | Символическое значение |
| --- | --- |
| `alert` | LOG\_ALERT |
| `crit` или `critical` | LOG\_CRIT |
| `debug` | LOG\_DEBUG |
| `emerg` или `panic` | LOG\_EMERG |
| `err` или `error` | LOG\_ERR |
| `info` | LOG\_INFO |
| `notice` | LOG\_NOTICE |
| `warn` или `warning` | LOG\_WARNING |

**Средства**

| Имя (строка) | Символическое значение |
| --- | --- |
| `auth` | LOG\_AUTH |
| `authpriv` | LOG\_AUTHPRIV |
| `cron` | LOG\_CRON |
| `daemon` | LOG\_DAEMON |
| `ftp` | LOG\_FTP |
| `kern` | LOG\_KERN |
| `lpr` | LOG\_LPR |
| `mail` | LOG\_MAIL |
| `news` | LOG\_NEWS |
| `syslog` | LOG\_SYSLOG |
| `user` | LOG\_USER |
| `uucp` | LOG\_UUCP |
| `local0` | LOG\_LOCAL0 |
| `local1` | LOG\_LOCAL1 |
| `local2` | LOG\_LOCAL2 |
| `local3` | LOG\_LOCAL3 |
| `local4` | LOG\_LOCAL4 |
| `local5` | LOG\_LOCAL5 |
| `local6` | LOG\_LOCAL6 |
| `local7` | LOG\_LOCAL7 |

#### `mapPriority(levelname)`

Сопоставляет имя уровня логирования с именем приоритета syslog. Возможно, потребуется переопределить этот метод, если используются пользовательские уровни или если алгоритм по умолчанию не подходит. Алгоритм по умолчанию сопоставляет `DEBUG`, `INFO`, `WARNING`, `ERROR` и `CRITICAL` с соответствующими именами syslog, а все остальные имена уровней – с 'warning'.

## NTEventLogHandler

Класс [`NTEventLogHandler`](https://python-all.ru/3.15/library/logging.handlers.html#logging.handlers.NTEventLogHandler), находящийся в модуле `logging.handlers`, поддерживает отправку сообщений логирования в локальный журнал событий Windows NT, Windows 2000 или Windows XP. Перед использованием необходимо установить расширения Win32 для Python от Марка Хаммонда.

#### `class logging.handlers.NTEventLogHandler(appname, dllname=None, logtype='Application')`

Возвращает новый экземпляр класса `NTEventLogHandler`. Аргумент *appname* используется для определения имени приложения, отображаемого в журнале событий. С использованием этого имени создаётся соответствующая запись в реестре. *dllname* должен содержать полный путь к .dll или .exe, содержащему определения сообщений для размещения в журнале (если не указан, используется `'win32service.pyd'` – он устанавливается вместе с расширениями Win32 и содержит несколько базовых placeholder-определений сообщений. Обратите внимание: использование этих placeholder-ов приведёт к увеличению размера журналов событий, так как в журнал сохраняется весь исходный код сообщения. Если нужны более компактные журналы, необходимо передать имя собственного .dll или .exe, содержащего желаемые определения сообщений). *logtype* – одно из `'Application'`, `'System'` или `'Security'`, по умолчанию `'Application'`.

#### `close()`

На этом этапе можно удалить имя приложения из реестра как источник записей журнала событий. Однако после этого события не будут отображаться в средстве просмотра журнала событий так, как предполагалось – для получения имени .dll требуется доступ к реестру. Текущая версия этого не делает.

#### `emit(record)`

Определяет идентификатор сообщения, категорию и тип события, а затем записывает сообщение в журнал событий NT.

#### `getEventCategory(record)`

Возвращает категорию события для записи. Переопределите этот метод, чтобы указать собственные категории. Данная версия возвращает 0.

#### `getEventType(record)`

Возвращает тип события для записи. Переопределите этот метод, чтобы указать собственные типы. Данная версия выполняет сопоставление с помощью атрибута typemap обработчика, который устанавливается в `__init__()` как словарь, содержащий сопоставления для `DEBUG`, `INFO`, `WARNING`, `ERROR` и `CRITICAL`. Если используются собственные уровни, необходимо либо переопределить этот метод, либо поместить подходящий словарь в атрибут *typemap* обработчика.

#### `getMessageID(record)`

Возвращает идентификатор сообщения для записи. Если используются собственные сообщения, можно передавать *msg* в логгер как идентификатор, а не как строку форматирования. Затем в этом методе можно выполнить поиск по словарю для получения идентификатора сообщения. Данная версия возвращает 1 – базовый идентификатор сообщения в `win32service.pyd`.

## SMTPHandler

Класс [`SMTPHandler`](https://python-all.ru/3.15/library/logging.handlers.html#logging.handlers.SMTPHandler), находящийся в модуле `logging.handlers`, поддерживает отправку сообщений логирования на адрес электронной почты через SMTP.

#### `class logging.handlers.SMTPHandler(mailhost, fromaddr, toaddrs, subject, credentials=None, secure=None, timeout=1.0)`

Возвращает новый экземпляр класса `SMTPHandler`. Экземпляр инициализируется адресами отправителя и получателя, а также темой письма. *toaddrs* должен быть списком строк. Для указания нестандартного SMTP-порта используйте кортеж (host, port) для аргумента *mailhost*. Если используется строка, применяется стандартный SMTP-порт. Если SMTP-сервер требует аутентификации, можно указать кортеж (username, password) для аргумента *credentials*.

Чтобы указать использование защищённого протокола (TLS), передайте кортеж в аргумент *secure*. Он будет использоваться только при наличии учётных данных аутентификации. Кортеж должен быть либо пустым, либо содержать одно значение – имя файла ключа, либо два значения: имя файла ключа и сертификата. (Этот кортеж передаётся методу [`smtplib.SMTP.starttls()`](https://python-all.ru/3.15/library/smtplib.html#smtplib.SMTP.starttls).)

Для взаимодействия с SMTP-сервером можно задать тайм-аут с помощью аргумента *timeout*.

Изменено в версии 3.3: добавлен параметр *timeout*.

#### `emit(record)`

Форматирует запись и отправляет её указанным получателям.

#### `getSubject(record)`

Чтобы задать тему письма, зависящую от записи, переопределите этот метод.

## MemoryHandler

Класс [`MemoryHandler`](https://python-all.ru/3.15/library/logging.handlers.html#logging.handlers.MemoryHandler), расположенный в модуле `logging.handlers`, поддерживает буферизацию записей журнала в памяти с периодическим сбросом в целевой обработчик *target*. Сброс происходит, когда буфер заполнен или когда встречается событие указанного уровня важности или выше.

[`MemoryHandler`](https://python-all.ru/3.15/library/logging.handlers.html#logging.handlers.MemoryHandler) является подклассом более общего [`BufferingHandler`](https://python-all.ru/3.15/library/logging.handlers.html#logging.handlers.BufferingHandler), который является абстрактным классом. Он буферизует записи журнала в памяти. При добавлении каждой записи в буфер вызывается `shouldFlush()` для проверки необходимости сброса. Если сброс нужен, то `flush()` выполняет его.

#### `class logging.handlers.BufferingHandler(capacity)`

Инициализирует обработчик буфером указанной ёмкости. Здесь *capacity* означает количество буферизируемых записей журнала.

#### `emit(record)`

Добавляет запись в буфер. Если [`shouldFlush()`](https://python-all.ru/3.15/library/logging.handlers.html#logging.handlers.BufferingHandler.shouldFlush) возвращает true, вызывает [`flush()`](https://python-all.ru/3.15/library/logging.handlers.html#logging.handlers.BufferingHandler.flush) для обработки буфера.

#### `flush()`

Для экземпляра `BufferingHandler` сброс означает установку буфера в пустой список. Этот метод можно переопределить для реализации более полезного поведения при сбросе.

#### `shouldFlush(record)`

Возвращает `True`, если буфер заполнен. Этот метод можно переопределить для реализации собственных стратегий сброса.

#### `class logging.handlers.MemoryHandler(capacity, flushLevel=ERROR, target=None, flushOnClose=True)`

Возвращает новый экземпляр класса `MemoryHandler`. Экземпляр инициализируется буфером размером *capacity* (количество буферизируемых записей). Если *flushLevel* не указан, используется `ERROR`. Если *target* не указан, целевой обработчик нужно задать с помощью [`setTarget()`](https://python-all.ru/3.15/library/logging.handlers.html#logging.handlers.MemoryHandler.setTarget), прежде чем обработчик начнёт работать. Если *flushOnClose* задан как `False`, то буфер *не* сбрасывается при закрытии обработчика. Если не задан или задан как `True`, то при закрытии буфер сбрасывается, как и раньше.

Изменено в версии 3.6: добавлен параметр *flushOnClose*.

#### `close()`

Вызывает [`flush()`](https://python-all.ru/3.15/library/logging.handlers.html#logging.handlers.MemoryHandler.flush), устанавливает целевой обработчик в `None` и очищает буфер.

#### `flush()`

Для экземпляра `MemoryHandler` сброс означает отправку буферизированных записей целевому обработчику, если он задан. Буфер также очищается после отправки. Переопределите этот метод для изменения поведения.

#### `setTarget(target)`

Устанавливает целевой обработчик для данного обработчика.

#### `shouldFlush(record)`

Проверяет, заполнен ли буфер или поступила запись уровня *flushLevel* или выше.

## HTTPHandler

Класс [`HTTPHandler`](https://python-all.ru/3.15/library/logging.handlers.html#logging.handlers.HTTPHandler), расположенный в модуле `logging.handlers`, поддерживает отправку сообщений журнала на веб-сервер с использованием семантики `GET` или `POST`.

#### `class logging.handlers.HTTPHandler(host, url, method='GET', secure=False, credentials=None, context=None)`

Возвращает новый экземпляр класса `HTTPHandler`. Параметр *host* может быть в формате `host:port`, если требуется указать конкретный номер порта. Если *method* не указан, используется `GET`. Если *secure* равен true, будет использоваться HTTPS-соединение. Параметр *context* можно задать как экземпляр [`ssl.SSLContext`](https://python-all.ru/3.15/library/ssl.html#ssl.SSLContext) для настройки параметров SSL, используемых для HTTPS-соединения. Если указаны *credentials*, это должен быть кортеж из двух элементов – идентификатора пользователя и пароля, которые будут помещены в HTTP-заголовок 'Authorization' с использованием базовой аутентификации. Если указываются учётные данные, также следует указать secure=True, чтобы идентификатор и пароль не передавались в открытом виде.

Изменено в версии 3.5: добавлен параметр *context*.

#### `mapLogRecord(record)`

Возвращает словарь на основе `record`, который должен быть закодирован в URL-кодировку и отправлен на веб-сервер. Реализация по умолчанию просто возвращает `record.__dict__`. Этот метод можно переопределить, если, например, на веб-сервер нужно отправить только подмножество [`LogRecord`](https://python-all.ru/3.15/library/logging.html#logging.LogRecord), или если требуется более точная настройка того, что отправляется на сервер.

#### `emit(record)`

Отправляет запись на веб-сервер в виде словаря в URL-кодировке. Метод [`mapLogRecord()`](https://python-all.ru/3.15/library/logging.handlers.html#logging.handlers.HTTPHandler.mapLogRecord) используется для преобразования записи в словарь для отправки.

> **Примечание**
>
> Поскольку подготовка записи для отправки на веб-сервер не то же самое, что обычная операция форматирования, использование [`setFormatter()`](https://python-all.ru/3.15/library/logging.html#logging.Handler.setFormatter) для указания [`Formatter`](https://python-all.ru/3.15/library/logging.html#logging.Formatter) для `HTTPHandler` не даёт эффекта. Вместо вызова [`format()`](https://python-all.ru/3.15/library/logging.html#logging.Handler.format) этот обработчик вызывает [`mapLogRecord()`](https://python-all.ru/3.15/library/logging.handlers.html#logging.handlers.HTTPHandler.mapLogRecord), а затем [`urllib.parse.urlencode()`](https://python-all.ru/3.15/library/urllib.parse.html#urllib.parse.urlencode), чтобы закодировать словарь в форму, пригодную для отправки на веб-сервер.

## QueueHandler

Добавлено в версии 3.2.

Класс [`QueueHandler`](https://python-all.ru/3.15/library/logging.handlers.html#logging.handlers.QueueHandler), расположенный в модуле `logging.handlers`, поддерживает отправку сообщений журналирования в очередь, например в очередь, реализованную в модулях [`queue`](https://python-all.ru/3.15/library/queue.html#module-queue) или [`multiprocessing`](https://python-all.ru/3.15/library/multiprocessing.html#module-multiprocessing).

В сочетании с классом [`QueueListener`](https://python-all.ru/3.15/library/logging.handlers.html#logging.handlers.QueueListener), [`QueueHandler`](https://python-all.ru/3.15/library/logging.handlers.html#logging.handlers.QueueHandler) можно использовать, чтобы позволить обработчикам работать в отдельном потоке, отличном от того, который выполняет журналирование. Это важно в веб-приложениях и других сервисных приложениях, где потоки, обслуживающие клиентов, должны отвечать как можно быстрее, а любые потенциально медленные операции (например, отправка электронной почты через [`SMTPHandler`](https://python-all.ru/3.15/library/logging.handlers.html#logging.handlers.SMTPHandler)) выполняются в отдельном потоке.

#### `class logging.handlers.QueueHandler(queue)`

Возвращает новый экземпляр класса `QueueHandler`. Экземпляр инициализируется очередью для отправки сообщений. *очередь* может быть любым объектом, похожим на очередь; он используется как есть методом [`enqueue()`](https://python-all.ru/3.15/library/logging.handlers.html#logging.handlers.QueueHandler.enqueue), который должен знать, как отправлять в него сообщения. Очередь не *обязана* иметь API отслеживания задач, поэтому для *очередь* можно использовать экземпляры [`SimpleQueue`](https://python-all.ru/3.15/library/queue.html#queue.SimpleQueue).

> **Примечание**
>
> Если вы используете [`multiprocessing`](https://python-all.ru/3.15/library/multiprocessing.html#module-multiprocessing), следует избегать использования [`SimpleQueue`](https://python-all.ru/3.15/library/queue.html#queue.SimpleQueue) и вместо этого использовать [`multiprocessing.Queue`](https://python-all.ru/3.15/library/multiprocessing.html#multiprocessing.Queue).

> **Предупреждение**
>
> Модуль [`multiprocessing`](https://python-all.ru/3.15/library/multiprocessing.html#module-multiprocessing) использует внутренний регистратор, созданный и доступный через [`get_logger()`](https://python-all.ru/3.15/library/multiprocessing.html#multiprocessing.get_logger). [`multiprocessing.Queue`](https://python-all.ru/3.15/library/multiprocessing.html#multiprocessing.Queue) будет регистрировать сообщения уровня `DEBUG` при помещении элементов в очередь. Если эти сообщения журналирования обрабатываются `QueueHandler`, использующим тот же экземпляр `multiprocessing.Queue`, это приведёт к взаимоблокировке или бесконечной рекурсии.

#### `emit(record)`

Помещает в очередь результат подготовки LogRecord. В случае возникновения исключения (например, из-за заполнения ограниченной очереди) вызывается метод [`handleError()`](https://python-all.ru/3.15/library/logging.html#logging.Handler.handleError) для обработки ошибки. Это может привести к тому, что запись будет молча отброшена (если [`logging.raiseExceptions`](https://python-all.ru/3.15/library/logging.html#logging.raiseExceptions) равно `False`) или сообщение будет выведено в `sys.stderr` (если `logging.raiseExceptions` равно `True`).

#### `prepare(record)`

Подготавливает запись для помещения в очередь. Объект, возвращаемый этим методом, помещается в очередь.

Базовая реализация форматирует запись, объединяя сообщение, аргументы, исключение и информацию о стеке (если они есть). Она также удаляет не сериализуемые (unpickleable) элементы из записи на месте. В частности, она перезаписывает атрибуты `msg` и `message` записи объединённым сообщением (полученным вызовом метода [`format()`](https://python-all.ru/3.15/library/functions.html#format) обработчика) и устанавливает атрибуты `args`, `exc_info` и `exc_text` в значение `None`.

Этот метод можно переопределить, если требуется преобразовать запись в словарь или JSON-строку, или отправить изменённую копию записи, оставив оригинал нетронутым.

> **Примечание**
>
> Базовая реализация форматирует сообщение с аргументами, устанавливает атрибуты `message` и `msg` в отформатированное сообщение, а атрибуты `args` и `exc_text` в `None`, чтобы обеспечить сериализацию (pickling) и предотвратить дальнейшие попытки форматирования. Это означает, что обработчик на стороне [`QueueListener`](https://python-all.ru/3.15/library/logging.handlers.html#logging.handlers.QueueListener) не будет иметь информации для выполнения пользовательского форматирования, например, исключений. Возможно, вы захотите создать подкласс `QueueHandler` и переопределить этот метод, чтобы, например, избежать установки `exc_text` в `None`. Обратите внимание, что изменения `message` / `msg` / `args` связаны с обеспечением сериализуемости записи, и вы можете или не можете избежать этого в зависимости от того, являются ли ваши `args` сериализуемыми. (Заметьте, что вам, возможно, придётся учитывать не только свой код, но и код любых используемых библиотек.)

#### `enqueue(record)`

Помещает запись в очередь с помощью `put_nowait()`; этот метод можно переопределить, если требуется блокирующее поведение, тайм-аут или настраиваемая реализация очереди.

#### `listener`

При создании через конфигурацию с помощью [`dictConfig()`](https://python-all.ru/3.15/library/logging.config.html#logging.config.dictConfig) этот атрибут будет содержать экземпляр [`QueueListener`](https://python-all.ru/3.15/library/logging.handlers.html#logging.handlers.QueueListener) для использования с данным обработчиком. В противном случае он будет равен `None`.

Добавлено в версии 3.12.

## QueueListener

Добавлено в версии 3.2.

Класс [`QueueListener`](https://python-all.ru/3.15/library/logging.handlers.html#logging.handlers.QueueListener), расположенный в модуле `logging.handlers`, поддерживает получение сообщений журналирования из очереди, например из очереди, реализованной в модулях [`queue`](https://python-all.ru/3.15/library/queue.html#module-queue) или [`multiprocessing`](https://python-all.ru/3.15/library/multiprocessing.html#module-multiprocessing). Сообщения принимаются из очереди во внутреннем потоке и передаются в том же потоке одному или нескольким обработчикам для обработки. Хотя `QueueListener` сам по себе не является обработчиком, он документирован здесь, потому что работает в тесной связке с [`QueueHandler`](https://python-all.ru/3.15/library/logging.handlers.html#logging.handlers.QueueHandler).

В сочетании с классом [`QueueHandler`](https://python-all.ru/3.15/library/logging.handlers.html#logging.handlers.QueueHandler), [`QueueListener`](https://python-all.ru/3.15/library/logging.handlers.html#logging.handlers.QueueListener) можно использовать, чтобы позволить обработчикам работать в отдельном потоке, отличном от того, который выполняет журналирование. Это важно в веб-приложениях и других сервисных приложениях, где потоки, обслуживающие клиентов, должны отвечать как можно быстрее, а любые потенциально медленные операции (например, отправка электронной почты через [`SMTPHandler`](https://python-all.ru/3.15/library/logging.handlers.html#logging.handlers.SMTPHandler)) выполняются в отдельном потоке.

#### `class logging.handlers.QueueListener(queue, *handlers, respect_handler_level=False)`

Возвращает новый экземпляр класса `QueueListener`. Экземпляр инициализируется очередью для отправки сообщений и списком обработчиков, которые будут обрабатывать записи, помещённые в очередь. Очередь может быть любым объектом, похожим на очередь; она передаётся как есть методу [`dequeue()`](https://python-all.ru/3.15/library/logging.handlers.html#logging.handlers.QueueListener.dequeue), который должен знать, как извлекать из неё сообщения. Очередь не *обязана* иметь API отслеживания задач (хотя он используется, если доступен), поэтому для *очередь* можно использовать экземпляры [`SimpleQueue`](https://python-all.ru/3.15/library/queue.html#queue.SimpleQueue).

> **Примечание**
>
> Если вы используете [`multiprocessing`](https://python-all.ru/3.15/library/multiprocessing.html#module-multiprocessing), следует избегать использования [`SimpleQueue`](https://python-all.ru/3.15/library/queue.html#queue.SimpleQueue) и вместо этого использовать [`multiprocessing.Queue`](https://python-all.ru/3.15/library/multiprocessing.html#multiprocessing.Queue).

Если `respect_handler_level` равно `True`, при принятии решения о передаче сообщений обработчику учитывается его уровень (сравнивается с уровнем сообщения); в противном случае поведение такое же, как в предыдущих версиях Python – всегда передавать каждое сообщение каждому обработчику.

Изменено в версии 3.5: Добавлен аргумент `respect_handler_level`.

Изменено в версии 3.14: `QueueListener` теперь можно использовать как контекстный менеджер через [`with`](https://python-all.ru/3.15/reference/compound_stmts.html#with). При входе в контекст слушатель запускается. При выходе из контекста слушатель останавливается. [`__enter__()`](https://python-all.ru/3.15/library/stdtypes.html#contextmanager.__enter__) возвращает объект `QueueListener`.

#### `dequeue(block)`

Извлекает запись из очереди и возвращает её, опционально блокируя.

Базовая реализация использует `get()`. Можно переопределить этот метод, если требуется использовать тайм-ауты или работать с нестандартными реализациями очереди.

#### `prepare(record)`

Подготавливает запись к обработке.

Эта реализация просто возвращает переданную запись. Можно переопределить этот метод, если требуется выполнить какую-либо собственную маршалинг или манипуляцию записью перед передачей обработчикам.

#### `handle(record)`

Обрабатывает запись.

Просто перебирает обработчики, передавая им запись на обработку. Реальный объект, передаваемый обработчикам, – это то, что возвращается из [`prepare()`](https://python-all.ru/3.15/library/logging.handlers.html#logging.handlers.QueueListener.prepare).

#### `start()`

Запускает прослушиватель.

Запускает фоновый поток для отслеживания очереди на предмет LogRecords, которые нужно обработать.

Изменено в версии 3.14: Вызывает [`RuntimeError`](https://python-all.ru/3.15/library/exceptions.html#RuntimeError) при вызове, если прослушиватель уже запущен.

#### `stop()`

Останавливает прослушиватель.

Запрашивает завершение потока и затем ожидает его завершения. Обратите внимание: если не вызвать этот метод до завершения приложения, в очереди могут остаться некоторые записи, которые не будут обработаны.

#### `enqueue_sentinel()`

Записывает сигнальный элемент в очередь, чтобы сообщить прослушивателю о завершении. Эта реализация использует `put_nowait()`. Можно переопределить этот метод, если требуется использовать тайм-ауты или работать с нестандартными реализациями очереди.

Добавлено в версии 3.3.

> **См. также**
>
> **Модуль [`logging`](https://python-all.ru/3.15/library/logging.html#module-logging)**
>
> Справочник API для модуля logging.
>
> **Модуль [`logging.config`](https://python-all.ru/3.15/library/logging.config.html#module-logging.config)**
>
> API конфигурации для модуля logging.
