MicroPython:Библиотеки/uasyncio
uasyncio – планировщик для асинхронных операций ввода/вывода[1]
В этом модуле реализована часть функционала соответствующего модуля CPython. Более подробно читайте в документации к CPython о модуле asyncio.
Пример:
import uasyncio
async def blink(led, period_ms):
while True:
led.on()
await uasyncio.sleep_ms(5)
led.off()
await uasyncio.sleep_ms(period_ms)
async def main(led1, led2):
uasyncio.create_task(blink(led1, 700))
uasyncio.create_task(blink(led2, 400))
await uasyncio.sleep_ms(10_000)
# Запуск на pyboard:
from pyb import LED
uasyncio.run(main(LED(1), LED(2)))
# Запуск на стандартной плате:
from machine import Pin
uasyncio.run(main(Pin(1), Pin(2)))
Ключевые функции
- uasyncio.create_task(coro) – создает новую задачу из заданной сопрограммы и планирует ее запуск. Возвращает соответствующий объект Task (см. ниже).
- uasyncio.run(coro) – создает новую задачу из заданной сопрограммы, запускает ее и ждет ее завершения. Возвращает значение, возвращенное coro.
- uasyncio.sleep(t) – режим сна на t секунд (значение в аргументе t может быть числом с плавающей точкой). Это сопрограмма.
- uasyncio.sleep_ms(t) – режим сна на t миллисекунд. Это сопрограмма, и в CPython этой функции нет, она сделана специально для MicroPython.
Дополнительные функции
- uasyncio.wait_for(awaitable, timeout) – ждет завершения задачи awaitable, но если время в таймере timeout истечет, задача будет прервана до своего выполнения. Если awaitable – это не задача, то из этого аргумента будет сделана задача.
Если таймаут истечет, задача будет прервана, а затем будет возбуждено исключение asyncio.TimeoutError. Инициатор вызова должен быть готов, чтобы перехватить это исключение. Возвращает значение, возвращенное awaitable. Это сопрограмма.
- uasyncio.wait_for_ms(awaitable, timeout) – делает то же самое, что и wait_for(), но timeout – это целое число в миллисекундах.
Это сопрограмма, и в CPython ее нет, она сделана специально для MicroPython.
- uasyncio.gather(\*awaitables, return_exceptions=False) – запускает все awaitables одновременно. Все awaitable, не являющиеся задачами, повышаются до задач.
Возвращает список значений, возвращенных всеми задачами в awaitables. Это сопрограмма.
Класс Task
- Класс uasyncio.Task – этот объект обертывает сопрограмму в запускаемую задачу. В MicroPython есть функции для ожидания выполнения задач – wait_for() и wait_for_ms() – которые после выполнения задачи возвращают значение, возвращенное этой задачей.
Задачи не должны создаваться напрямую. Используйте для этого функцию create_task().
- Task.cancel() – отменяет выполнение задачи, внедряя в нее ошибку CancelledError. Задача может проигнорировать это исключение.
Класс Event
- classuasyncio.Event – создает новое событие, которое можно использовать для синхронизации задач. События запускаются в «очищенном» состоянии.
- Event.is_set() – возвращает True, если событие находится во «включенном» состоянии, в противном случае возвращает False.
- Event.set() – переводит событие во «включенное» состояние. Все задачи, ждущие этого события, будут запланированы к запуску.
- Event.clear() – «очищает» событие.
- Event.wait() – ждет, пока событие будет переведено во «включенное» состояние. Если событие уже находится в таком состоянии, мгновенно возвращает True.
Это сопрограмма.
Класс Lock
- Класс uasyncio.Lock – создает новую блокировку, которую можно использовать для координации задач. Блокировки начинают работать в разблокированном состоянии.
Вдобавок к методам ниже, блокировки можно использовать в операторе async with.
- Lock.locked() – возвращает True, если блокировка заблокирована, а в противном случае возвращает False.
- Lock.acquire() – ждет, пока блокировка не разблокируется, а затем ставит блокировку. Одновременно блокировку может удерживать только одна сопрограмма.
Это сопрограмма.
- Lock.release() – снимает блокировку (т.е. перестает ее удерживать). Если при этом есть задачи, ожидающие снятия блокировки, то та из них, что первая стоит в очереди, будет запланирована на запуск, после чего блокировка снова будет активирована. В противном случае не будет разблокирована ни одна задача.
Потоковые TCP-соединения
- uasyncio.open_connection(host, port) – открывает TCP-соединение, используя заданные хост (host) и порт (port). Адрес хоста можно узнать при помощи функции socket.getaddrinfo(), которая в данный момент является блокирующей функцией.
Возвращает два потока: для чтения и записи. Если не получается узнать адрес хоста или установить соединение, будет выдана сокетная ошибка OSError. Это сопрограмма.
- uasyncio.start_server(callback, host, port, backlog=5) – запускает TCP-сервер на заданных хосте (host) и порте (port). При каждом подключении к клиенту будет вызвана функция обратного вызова callback, которой для подключения будут переданы два аргумента: потоки для чтения и записи.
Возвращает объект Server (см. ниже). Это сопрограмма.
- Класс uasyncio.Stream – это класс для потокового TCP-соединения. Чтобы минимизировать код, в этом классе реализованы одновременно классы StreamReader (для чтения) и StreamWriter (для записи).
- Stream.get_extra_info(v) – считывает дополнительную информацию о потоке v. Пример корректного значения для аргумента v: peername.
- Stream.close() – закрывает поток.
- Stream.wait_closed() – ждет закрытия потока. Это сопрограмма.
- Stream.read(n) – считывает до n байтов и возвращает их. Это сопрограмма.
- Stream.readline() – считывает строку и возвращает ее. Это сопрограмма.
- Stream.write(buf) – аккумулирует данные в буфер buf. Данные в буфере будут стерты только после вызова Stream.drain() (см. ниже). Рекомендуется вызывать Stream.drain() сразу после вызова этой функции.
- Stream.drain() – «иссушает» буфер, т.е. записывает все данные из него в поток. Это сопрограмма.
- Класс uasyncio.Server – это серверный класс, возвращаемый функцией start_server() (см. выше). Его можно использовать в операторе async with, чтобы закрыть сервер при выходе.
- Server.close() – закрывает сервер.
- Server.wait_closed() – ждет закрытия сервера. Это сопрограмма.
Цикл событий
- uasyncio.get_event_loop() – возвращает цикл событий, использовавшийся для планирования и запуска задач. Более подробно читайте ниже (см. класс Loop).
- uasyncio.new_event_loop() – сбрасывает цикл событий и возвращает его.
Примечание: Поскольку в MicroPython только один цикл событий, эта функция просто сбрасывает состояния цикла, а не создает новый.
- Класс uasyncio.Loop – объект для планирования и запуска задач. Создать его нельзя, поэтому чтобы получить доступ к нему, используйте функцию get_event_loop() (см. выше).
- Loop.create_task(coro) – создает задачу из заданной сопрограммы coro и возвращает новый объект Task.
- Loop.run_forever() – запускает цикл событий, который будет работать, пока не будет вызвана функция stop().
- Loop.run_until_complete(awaitable) – запускает заданную awaitable, и она будет работать, пока не завершится. Если объект awaitable – это не задача, то он будет «повышен» до задачи.
- Loop.stop() – останавливает цикл событий.
- Loop.close() – закрывает цикл событий.
- Loop.set_exception_handler(handler) – задает обработчик исключения, который будет вызван, когда задача возбудит невыловленное исключение. Этот обработчик должен принимать два аргумента: (loop, context).
- Loop.get_exception_handler() – возвращает текущий обработчик исключений или None, если обработчика исключений задано не было.
- Loop.default_exception_handler(context) – вызывает обработчик исключений, заданный по умолчанию.
- Loop.call_exception_handler(context) – вызывает текущий обработчик исключений. Аргумент context – это словарь с ключами 'message', 'exception', 'future'.