select — очікування подій на наборі потоків

Цей модуль надає функції для ефективного очікування готовності одного або більше потоків (файлоподібних об’єктів, що реалізують протокол потоку, наприклад сокетів, UART та інших об’єктів вводу-виводу) до читання або запису — замість активного очікування або блокування на одному об’єкті.

Рекомендованим інтерфейсом є об’єкт poll: він масштабується для багатьох потоків і не виконує виділення пам’яті при використанні через poll.ipoll(). Функція select() на рівні модуля є менш ефективним інтерфейсом для сумісності.

Приклад використання об’єкта poll

import select

poller = select.poll()
poller.register(uart, select.POLLIN)

while True:
    # Wait up to 1000 ms for the UART to have data.
    for obj, event in poller.poll(1000):
        if event & select.POLLIN:
            print(obj.read())

Приклад використання функції select() на рівні модуля:

import select

# Wait up to 1 second for the socket to become readable.
rlist, wlist, xlist = select.select([sock], [], [], 1.0)
if rlist:
    data = sock.recv(100)

Функції

select.select(rlist: List, wlist: List, xlist: List, timeout: float | None = None) Tuple[List, List, List]

Очікувати, поки один або більше з переданих об’єктів потоків не буде готовий, або до закінчення timeout.

  • rlist — список об’єктів для моніторингу на предмет готовності до читання.

  • wlist — список об’єктів для моніторингу на предмет готовності до запису.

  • xlist — список об’єктів для моніторингу на предмет помилок або зависання.

  • timeout — максимальний час очікування в секундах (приймається число з плаваючою комою). Якщо параметр відсутній або None, виклик блокується безстроково; 0 повертає результат негайно (неблокуючий опит).

Повертає 3-кортеж списків (rlist, wlist, xlist). Кожен повернутий список є підмножиною відповідного вхідного списку, що містить об’єкти, готові до читання, до запису або ті, що сигналізують про помилку чи зависання відповідно. Якщо timeout закінчується без готових об’єктів, всі три списки порожні.

Ця функція менш ефективна, ніж poll (вона перебудовує внутрішній набір опитування при кожному виклику); використовуйте poll там, де це можливо.

Константи

select.POLLIN: int

Є дані, доступні для читання з потоку.

select.POLLOUT: int

Потік може прийняти більше даних для запису.

select.POLLERR: int

На потоці виникла умова помилки. Це небажана подія: вона повідомляється методами poll.poll() / poll.ipoll() навіть якщо її не було запрошено в eventmask, і передавати її як вхідний eventmask неприпустимо.

select.POLLHUP: int

Потік був відключений / роз’єднаний. Це небажана подія: вона повідомляється методами poll.poll() / poll.ipoll() навіть якщо її не було запрошено в eventmask, і передавати її як вхідний eventmask неприпустимо.

Класи

class select.poll

Створити об’єкт опитування, що підтримує набір зареєстрованих потоків (або будь-яких об’єктів, що реалізують протокол потоку) та ефективно очікує, поки один або більше з них не стане готовим до читання, запису або не сигналізує про виняткову умову.

Потоки додаються за допомогою register(), видаляються за допомогою unregister(), а набір подій для відстеження можна змінити за допомогою modify(). Після налаштування викликайте poll() для блокування до готовності чогось (або до закінчення таймауту), або ipoll() для варіанта на основі ітератора без виділення пам’яті.

register(obj: Any, eventmask: int = select.POLLIN | select.POLLOUT) None

Зареєструвати stream obj для опитування, відстежуючи події, задані eventmask (логічне АБО):

  • select.POLLIN – дані доступні для читання

  • select.POLLOUT – потік може прийняти більше даних для запису

eventmask за замовчуванням дорівнює select.POLLIN | select.POLLOUT.

select.POLLHUP та select.POLLERR не є дійсними у вхідному eventmask — вони є небажаними подіями, що повідомляються методами poll() / ipoll() незалежно від того, чи були вони запрошені (це відповідає семантиці POSIX).

Можна викликати цей метод більше одного разу для одного і того ж obj: подальший виклик оновлює маску подій obj, поводячись як modify().

unregister(obj: Any) None

Видалити obj з набору зареєстрованих потоків. Відміна реєстрації об’єкта obj, який наразі не зареєстрований, не є помилкою (виклик не має жодного ефекту в цьому випадку).

modify(obj: Any, eventmask: int) None

Змінити маску подій для вже зареєстрованого obj на eventmask. Виникає OSError з errno.ENOENT, якщо obj не зареєстровано.

poll(timeout: int = -1, /) List[Tuple]

Блокувати до готовності хоча б одного зареєстрованого потоку або сигналу виняткової умови, потім повернути список потоків, що спрацювали.

timeout — максимальний час очікування у мілісекундах. Якщо параметр відсутній або -1, виклик блокується безстроково; 0 повертає результат негайно (неблокуючий опит).

Повертає список кортежів (obj, event, ...), по одному на кожен потік, що спрацював. obj — зареєстрований потік, а event — побітове АБО прапорів select.POLLIN / select.POLLOUT / select.POLLERR / select.POLLHUP, що відбулися. Кожен кортеж може містити додаткові елементи, визначені реалізацією, тому не припускайте довжину рівно 2. Якщо timeout закінчується без готових об’єктів, повертається порожній список.

select.POLLHUP та select.POLLERR можуть повертатися в будь-який час (навіть без запиту) і на них необхідно реагувати — зазвичай шляхом відміни реєстрації та закриття відповідного потоку — інакше подальші виклики продовжуватимуть повертати результат негайно з цими встановленими прапорами для даного потоку.

Гарантується, що всі заплановані зворотні виклики виконаються до початку циклу опитування.

Відмінність від CPython

Повернуті кортежі можуть містити більше 2 елементів, як описано вище.

ipoll(timeout: int = -1, flags: int = 0, /) Iterator[Tuple]

Як poll(), але замість побудови списку повертає ітератор, що видає по одному кортежу (obj, event, ...) за раз. Це дозволяє уникнути виділення пам’яті при кожному виклику, що важливо для асинхронних планувальників вводу-виводу.

Повернутий кортеж є власністю викликаного: він повторно використовується (перезаписується) на наступній ітерації, тому його вміст потрібно обробити в тілі циклу, а посилання на нього зберігати не можна.

timeout має те саме значення, що й для poll(). Якщо flags дорівнює 1, використовується одноразова поведінка: потік, чия подія спрацювала, автоматично очищує свою маску подій (еквівалентно poll.modify(obj, 0)), тому більше жодних подій для нього не повідомляється, поки його маску не буде знову встановлено за допомогою modify().

Гарантується, що всі заплановані зворотні виклики виконаються до початку циклу опитування.

Відмінність від CPython

Цей метод є розширенням MicroPython.