asyncio之定时调度常规函数

定时调度常规函数

除了管理协程和I/O回调,asyncio事件循环还可以基于循环中的时间计数器值来调度常规函数。

计划调度“Soon”

如果回调的时间无关紧要,call_soon()函数可以被用来调度函数执行,函数之后的任何额外的参数都会被传递给被调用的函数。为了将关键字参数传递给回调函数,我们是用functools模块的 partial()函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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()

这种回调是按照预定的顺序调用的。

1
2
3
4
5
6
7
$ 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()函数。第一个参数是要延迟的时间秒数,第二个参数是要回调的函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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()函数却在前面调度运行,表明“soon”是马上进行调度运行的。

1
2
3
4
5
6
7
8
$ python3 asyncio_call_later.py
entering event loop
registering callbacks
callback 3 invoked
callback 2 invoked
callback 1 invoked
closing event loop

特定时间调度

还可以在一个特定的时间点进行调度。事件循环使用的是一个monotonic clock而不是一个wall-clock时间,以确保“now”的值永远不会倒退。要在特定的时间进行调度必须从循环的内部时间“now()”开始。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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()。

1
2
3
4
5
6
7
8
9
10
$ python3 asyncio_call_at.py
entering event loop
clock time: 1479050248.66192
loop time: 1008846.13856885
registering callbacks
callback 3 invoked at 1008846.13867956
callback 2 invoked at 1008846.239931555
callback 1 invoked at 1008846.343480996
closing event loop

本文翻译自《The Python3 Standard Library By Example》asyncio相关章节

文章目录
  1. 1. 计划调度“Soon”
  2. 2. 延迟调度
  3. 3. 特定时间调度
|