Автор оригинала: Doug Hellmann.
В дополнение к управлению сопрограммами и обратными вызовами ввода-вывода цикл событий asyncio
может планировать вызовы обычных функций на основе значения таймера, хранящегося в цикле.
Планирование обратного вызова “Скоро”
Если время обратного вызова не имеет значения, можно использовать call_soon ()
для планирования вызова для следующей итерации цикла. Любые дополнительные позиционные аргументы после функции передаются обратному вызову при ее вызове. Чтобы передать аргументы ключевого слова в обратный вызов, используйте partial ()
из модуля functools.
asyncio_call_soon.py
import asyncio import functools def callback(arg, *, kwarg'default'): print('callback invoked with {} and {}'.format(arg, kwarg)) async def main(loop): print('registering callbacks') loop.call_soon(callback, 1) wrapped functools.partial(callback, kwarg'not default') loop.call_soon(wrapped, 2) await asyncio.sleep(0.1) event_loop asyncio.get_event_loop() try: print('entering event loop') event_loop.run_until_complete(main(event_loop)) finally: print('closing event loop') event_loop.close()
Обратные вызовы вызываются в том порядке, в котором они запланированы.
$ python3 asyncio_call_soon.py entering event loop registering callbacks callback invoked with 1 and default callback invoked with 2 and not default closing event loop
Планирование обратного вызова с задержкой
Чтобы отложить обратный вызов на некоторое время в будущем, используйте call_later ()
. Первый аргумент – это задержка в секундах, а второй аргумент – это обратный вызов.
asyncio_call_later.py
import asyncio def callback(n): print('callback {} invoked'.format(n)) async def main(loop): print('registering callbacks') loop.call_later(0.2, callback, 1) loop.call_later(0.1, callback, 2) loop.call_soon(callback, 3) await asyncio.sleep(0.4) event_loop asyncio.get_event_loop() try: print('entering event loop') event_loop.run_until_complete(main(event_loop)) finally: print('closing event loop') event_loop.close()
В этом примере одна и та же функция обратного вызова запланирована несколько раз с разными аргументами. Последний экземпляр, использующий call_soon ()
, приводит к тому, что обратный вызов вызывается с аргументом 3
перед любым из запланированных по времени экземпляров, показывая, что “скоро” обычно подразумевает минимальная задержка.
$ python3 asyncio_call_later.py entering event loop registering callbacks callback 3 invoked callback 2 invoked callback 1 invoked closing event loop
Планирование обратного вызова на определенное время
Также можно запланировать вызов в определенное время. В цикле используются монотонные часы, а не настенные часы, чтобы значение «сейчас» никогда не регрессировало. Чтобы выбрать время для запланированного обратного вызова, необходимо начать с внутреннего состояния этих часов, используя метод цикла time ()
.
asyncio_call_at.py
import asyncio import time def callback(n, loop): print('callback {} invoked at {}'.format(n, loop.time())) async def main(loop): now loop.time() print('clock time: {}'.format(time.time())) print('loop time: {}'.format(now)) print('registering callbacks') loop.call_at(now + 0.2, callback, 1, loop) loop.call_at(now + 0.1, callback, 2, loop) loop.call_soon(callback, 3, loop) await asyncio.sleep(1) event_loop asyncio.get_event_loop() try: print('entering event loop') event_loop.run_until_complete(main(event_loop)) finally: print('closing event loop') event_loop.close()
Обратите внимание, что время в соответствии с циклом не соответствует значению, возвращаемому time.time ()
.
$ python3 asyncio_call_at.py entering event loop clock time: 1521404411.833459 loop time: 715855.398664185 registering callbacks callback 3 invoked at 715855.398744743 callback 2 invoked at 715855.503897727 callback 1 invoked at 715855.601119414 closing event loop