Перейти к содержимому

18.4. selectors – мультиплексирование ввода-вывода высокого уровня

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

Исходный код: Lib/selectors.py


18.4.1. Введение

Этот модуль позволяет выполнять высокоуровневый и эффективный мультиплексинг ввода-вывода, построенный на примитивах модуля select. Пользователям рекомендуется использовать этот модуль, если только им не нужен точный контроль над используемыми примитивами уровня ОС.

Он определяет абстрактный базовый класс BaseSelector вместе с несколькими конкретными реализациями (KqueueSelector, EpollSelector…), которые можно использовать для ожидания уведомлений о готовности ввода-вывода для нескольких файловых объектов. В дальнейшем «файловый объект» означает любой объект с методом fileno() или сырой файловый дескриптор. См. файловый объект.

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

Примечание

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

Смотрите также

select

Модуль низкоуровневого мультиплексинга ввода-вывода.

18.4.2. Классы

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

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

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

Константа

Значение

EVENT_READ

Доступно для чтения

EVENT_WRITE

Доступно для записи

classselectors.SelectorKey

SelectorKey – это namedtuple, используемая для связи файлового объекта с его базовым файловым дескриптором, выбранной маской событий и присоединёнными данными. Она возвращается несколькими методами BaseSelector.

fileobj

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

fd

Базовый файловый дескриптор.

events

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

data

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

classselectors.BaseSelector

BaseSelector используется для ожидания готовности событий ввода-вывода для нескольких файловых объектов. Он поддерживает регистрацию и отмену регистрации файловых потоков, а также метод для ожидания событий ввода-вывода на этих потоках с возможностью указания тайм-аута. Это абстрактный базовый класс, поэтому его нельзя инстанциировать. Используйте DefaultSelector вместо него или один из SelectSelector, KqueueSelector и т.д., если вы хотите использовать конкретную реализацию, и ваша платформа её поддерживает. BaseSelector и его конкретные реализации поддерживают протокол менеджер контекста.

abstractmethod register(fileobj, events, data=None)

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

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

Это возвращает новый экземпляр SelectorKey или возбуждает ValueError в случае недопустимой маски событий или файлового дескриптора, или KeyError, если файловый объект уже зарегистрирован.

abstractmethod unregister(fileobj)

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

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

Этот метод возвращает связанный экземпляр SelectorKey или вызывает исключение KeyError, если fileobj не зарегистрирован. Он вызовет ValueError, если fileobj некорректен (например, у него нет метода fileno() или его метод fileno() возвращает недопустимое значение).

modify(fileobj, events, data=None)

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

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

Возвращает новый экземпляр SelectorKey или вызывает ValueError в случае недопустимой маски событий или файлового дескриптора, либо KeyError, если файловый объект не зарегистрирован.

abstractmethod select(timeout=None)

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

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

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

key – это экземпляр SelectorKey, соответствующий готовому файловому объекту. events – это битовая маска событий, готовых для этого файлового объекта.

Примечание

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

Изменено в версии 3.5: Теперь при прерывании сигналом селектор повторяет попытку с пересчитанным тайм-аутом, если обработчик сигнала не вызвал исключение (см. PEP 475 для обоснования), вместо того чтобы возвращать пустой список событий до истечения тайм-аута.

close()

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

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

get_key(fileobj)

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

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

abstractmethodget_map()

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

Возвращает экземпляр Mapping, отображающий зарегистрированные файловые объекты на соответствующие экземпляры SelectorKey.

classselectors.DefaultSelector

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

classselectors.SelectSelector

Селектор на основе select.select().

classselectors.PollSelector

Селектор на основе select.poll().

classselectors.EpollSelector

Селектор на основе select.epoll().

fileno()

Возвращает файловый дескриптор, используемый нижележащим объектом select.epoll().

classselectors.DevpollSelector

Селектор на основе select.devpoll().

fileno()

Возвращает файловый дескриптор, используемый нижележащим объектом select.devpoll().

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

classselectors.KqueueSelector

Селектор на основе select.kqueue().

fileno()

Возвращает файловый дескриптор, используемый нижележащим объектом 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)