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

---

# 18.4. [`selectors`](https://python-all.ru/3.4/library/selectors.html#module-selectors) – Высокоуровневая мультиплексация ввода-вывода

Новое в версии 3.4.

## 18.4.1. Введение

Этот модуль предоставляет высокоуровневую и эффективную мультиплексацию ввода-вывода, построенную на примитивах модуля [`select`](https://python-all.ru/3.4/library/select.html#module-select). Пользователям рекомендуется использовать именно этот модуль, если только они не хотят точного контроля над используемыми примитивами уровня ОС.

В нём определяется абстрактный базовый класс [`BaseSelector`](https://python-all.ru/3.4/library/selectors.html#selectors.BaseSelector), а также несколько конкретных реализаций ([`KqueueSelector`](https://python-all.ru/3.4/library/selectors.html#selectors.KqueueSelector), [`EpollSelector`](https://python-all.ru/3.4/library/selectors.html#selectors.EpollSelector)...), которые можно использовать для ожидания уведомлений о готовности ввода-вывода для нескольких файловых объектов. В дальнейшем под «файловым объектом» понимается любой объект с методом `fileno()` или целочисленный файловый дескриптор. См. [*file object*](https://python-all.ru/3.4/glossary.html#term-file-object).

[`DefaultSelector`](https://python-all.ru/3.4/library/selectors.html#selectors.DefaultSelector) – это псевдоним наиболее эффективной реализации, доступной на текущей платформе; это должен быть выбор по умолчанию для большинства пользователей.

> **Примечание**
>
> Тип поддерживаемых файловых объектов зависит от платформы: в Windows поддерживаются сокеты, но не каналы, тогда как в Unix поддерживаются и сокеты, и каналы (также могут поддерживаться и другие типы, например именованные каналы или специальные файловые устройства).

> **См. также**
>
> **[`select`](https://python-all.ru/3.4/library/select.html#module-select)**
>
> Модуль низкоуровневого мультиплексирования ввода-вывода.

## 18.4.2. Классы

Иерархия классов:

```python
BaseSelector
+-- SelectSelector
+-- PollSelector
+-- EpollSelector
+-- KqueueSelector
```

В дальнейшем *events* – это битовая маска, указывающая, какие события ввода-вывода следует ожидать для данного файлового объекта. Она может быть комбинацией следующих констант:

> | Константа | Значение |
> | --- | --- |
> | `EVENT_READ` | Доступен для чтения |
> | `EVENT_WRITE` | Доступен для записи |

#### `class selectors.SelectorKey`

[`SelectorKey`](https://python-all.ru/3.4/library/selectors.html#selectors.SelectorKey) – это [`namedtuple`](https://python-all.ru/3.4/library/collections.html#collections.namedtuple), используемый для связи файлового объекта с его базовым файловым дескриптором, выбранной маской событий и прикреплёнными данными. Он возвращается несколькими методами [`BaseSelector`](https://python-all.ru/3.4/library/selectors.html#selectors.BaseSelector).

#### `fileobj`

Зарегистрированный файловый объект.

#### `fd`

Нижележащий файловый дескриптор.

#### `events`

События, которые необходимо ожидать для этого файлового объекта.

#### `data`

Необязательные непрозрачные данные, связанные с этим файловым объектом: например, их можно использовать для хранения идентификатора сессии для каждого клиента.

#### `class selectors.BaseSelector`

[`BaseSelector`](https://python-all.ru/3.4/library/selectors.html#selectors.BaseSelector) используется для ожидания готовности событий ввода-вывода на нескольких файловых объектах. Он поддерживает регистрацию и отмену регистрации файловых потоков, а также метод для ожидания событий ввода-вывода на этих потоках с необязательным тайм-аутом. Это абстрактный базовый класс, поэтому его нельзя инстанциировать. Используйте [`DefaultSelector`](https://python-all.ru/3.4/library/selectors.html#selectors.DefaultSelector) или один из [`SelectSelector`](https://python-all.ru/3.4/library/selectors.html#selectors.SelectSelector), [`KqueueSelector`](https://python-all.ru/3.4/library/selectors.html#selectors.KqueueSelector) и т. д., если вы хотите использовать конкретную реализацию, и ваша платформа её поддерживает. [`BaseSelector`](https://python-all.ru/3.4/library/selectors.html#selectors.BaseSelector) и его конкретные реализации поддерживают протокол [*менеджера контекста*](https://python-all.ru/3.4/glossary.html#term-context-manager).

#### `register(fileobj, events, data=None)`

Регистрирует файловый объект для выбора, отслеживая события ввода-вывода.

*fileobj* – это файловый объект для наблюдения. Он может быть целочисленным файловым дескриптором или объектом с методом `fileno()`. *events* – битовая маска событий для наблюдения. *data* – непрозрачный объект.

Возвращает новый экземпляр [`SelectorKey`](https://python-all.ru/3.4/library/selectors.html#selectors.SelectorKey) или вызывает [`ValueError`](https://python-all.ru/3.4/library/exceptions.html#ValueError) в случае недопустимой маски событий или файлового дескриптора, или [`KeyError`](https://python-all.ru/3.4/library/exceptions.html#KeyError), если файловый объект уже зарегистрирован.

#### `unregister(fileobj)`

Отменяет регистрацию файлового объекта, удаляя его из отслеживания. Файловый объект должен быть отменён до закрытия.

*fileobj* должен быть ранее зарегистрированным файловым объектом.

Возвращает соответствующий экземпляр [`SelectorKey`](https://python-all.ru/3.4/library/selectors.html#selectors.SelectorKey) или вызывает [`KeyError`](https://python-all.ru/3.4/library/exceptions.html#KeyError), если *fileobj* не зарегистрирован. Также вызовет [`ValueError`](https://python-all.ru/3.4/library/exceptions.html#ValueError), если *fileobj* недопустим (например, у него нет метода `fileno()` или его метод `fileno()` возвращает недопустимое значение).

#### `modify(fileobj, events, data=None)`

Изменяет отслеживаемые события или присоединённые данные зарегистрированного файлового объекта.

Это эквивалентно вызову `BaseSelector.unregister(fileobj)()` с последующим `BaseSelector.register(fileobj, events, data)()`, за исключением того, что это может быть реализовано более эффективно.

Возвращает новый экземпляр [`SelectorKey`](https://python-all.ru/3.4/library/selectors.html#selectors.SelectorKey) или вызывает [`ValueError`](https://python-all.ru/3.4/library/exceptions.html#ValueError) в случае недопустимой маски событий или файлового дескриптора, или [`KeyError`](https://python-all.ru/3.4/library/exceptions.html#KeyError), если файловый объект не зарегистрирован.

#### `select(timeout=None)`

Ожидает, пока некоторые зарегистрированные файловые объекты не станут готовы, или пока не истечёт тайм-аут.

Если `timeout > 0`, это задаёт максимальное время ожидания в секундах. Если `timeout <= 0`, вызов не будет блокироваться и сообщит о текущих готовых файловых объектах. Если *timeout* равен `None`, вызов будет блокироваться, пока контролируемый файловый объект не станет готов.

Возвращает список кортежей `(key, events)` по одному для каждого готового файлового объекта.

*key* – это экземпляр [`SelectorKey`](https://python-all.ru/3.4/library/selectors.html#selectors.SelectorKey), соответствующий готовому файловому объекту. *events* – битовая маска событий, готовых на этом файловом объекте.

> **Примечание**
>
> Этот метод может вернуть результат до того, как какой-либо файловый объект станет готовым или истечёт тайм-аут, если текущий процесс получает сигнал: в этом случае будет возвращён пустой список.

#### `close()`

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

Должен быть вызван, чтобы гарантировать освобождение всех базовых ресурсов. Селектор нельзя использовать после его закрытия.

#### `get_key(fileobj)`

Возвращает ключ, связанный с зарегистрированным файловым объектом.

Возвращает экземпляр [`SelectorKey`](https://python-all.ru/3.4/library/selectors.html#selectors.SelectorKey), связанный с этим файловым объектом, или вызывает [`KeyError`](https://python-all.ru/3.4/library/exceptions.html#KeyError), если файловый объект не зарегистрирован.

#### `get_map()`

Возвращает отображение файловых объектов на ключи селектора.

Возвращает экземпляр [`Mapping`](https://python-all.ru/3.4/library/collections.abc.html#collections.abc.Mapping), который сопоставляет зарегистрированные файловые объекты с соответствующими экземплярами [`SelectorKey`](https://python-all.ru/3.4/library/selectors.html#selectors.SelectorKey) .

#### `class selectors.DefaultSelector`

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

#### `class selectors.SelectSelector`

Селектор на основе [`select.select()`](https://python-all.ru/3.4/library/select.html#select.select).

#### `class selectors.PollSelector`

Селектор на основе [`select.poll()`](https://python-all.ru/3.4/library/select.html#select.poll).

#### `class selectors.EpollSelector`

Селектор на основе [`select.epoll()`](https://python-all.ru/3.4/library/select.html#select.epoll).

#### `fileno()`

Возвращает файловый дескриптор, используемый нижележащим объектом [`select.epoll()`](https://python-all.ru/3.4/library/select.html#select.epoll).

#### `class selectors.KqueueSelector`

Селектор на основе [`select.kqueue()`](https://python-all.ru/3.4/library/select.html#select.kqueue).

#### `fileno()`

Возвращает файловый дескриптор, используемый нижележащим объектом [`select.kqueue()`](https://python-all.ru/3.4/library/select.html#select.kqueue).

## 18.4.3. Примеры

Ниже приведена простая реализация эхо-сервера:

```python
import selectors
import socket

sel = selectors.DefaultSelector()

def accept(sock, mask):
    conn, addr = sock.accept()  # Должен быть готов
    print('accepted', conn, 'from', addr)
    conn.setblocking(False)
    sel.register(conn, selectors.EVENT_READ, read)

def read(conn, mask):
    data = conn.recv(1000)  # Должен быть готов
    if data:
        print('echoing', repr(data), 'to', conn)
        conn.send(data)  # Надеюсь, не заблокируется
    else:
        print('closing', conn)
        sel.unregister(conn)
        conn.close()

sock = socket.socket()
sock.bind(('localhost', 1234))
sock.listen(100)
sock.setblocking(False)
sel.register(sock, selectors.EVENT_READ, accept)

while True:
    events = sel.select()
    for key, mask in events:
        callback = key.data
        callback(key.fileobj, mask)
```
