定义
<li>asyncio模块提供了围绕event loop的框架。event_loop 事件循环等待满足某事件的发生,然后在事件上调取相应的函数。“when event A happens, react with function B”
<li>coroutine 协程 是一个特殊的函数,当调用时不会立即执行函数,而是会返回一个协程对象。你可以把coroutine对象传到event loop中,有event loop选择是立即调用还是推后执行。
<li>future 代表将来执行或没有执行的任务的结果。event loop能够件事future对象并且等到它执行。
<li>task 对coroutine的封装,是future的子类
async 和@asyncio.coroutine
用来定义一个协程。
import asyncio
@asyncio.coroutine
def my_coro():
yield from func()
>>>>
async def my_coro():
await func()
>>>两种定义协程的方式
</pre>
例如
<pre>
import asyncio
import random
@asyncio.coroutine
def my_coro():
ran = random.randint(1,1000)
print(ran)
coroutine = my_coro()
loop = asyncio.get_event_loop()
loop.run_until_complete(coroutine)
loop.close()
>>>216
协程换成如下定义也行
async def my_coro():
ran = random.randint(1,1000)
print(ran)
函数调度
call_soon(callback, *args)
call_soon_threadsafe(callback, *args)
安排一个回调一遍尽快调用
import asyncio
import functools
import time
now = lambda : time.strftime('%Y-%m-%d %H:%M:%S')
def event_handler(loop,stop=False):
time.sleep(1)
print('Event handler called',now())
if stop:
print('stopping the loop',now())
loop.stop()
if __name__=='__main__':
loop = asyncio.get_event_loop()
try:
loop.call_soon(functools.partial(event_handler,loop))
print('starting event loop:',now())
loop.call_soon(functools.partial(event_handler,loop,stop=True))
loop.run_forever()
finally:
print('closing event loop',now())
loop.close()
>>>
starting event loop: 2017-07-06 21:58:24
Event handler called 2017-07-06 21:58:25
Event handler called 2017-07-06 21:58:26
stopping the loop 2017-07-06 21:58:26
closing event loop 2017-07-06 21:58:26
call_later(delay, callback, *args)
loop.call_later(1, event_handler, loop) 推迟1s执行event_handle
基于event loop的记时
current_time = loop.time()
Tasks
所谓task对象是Future类的子类。保存了协程运行后的状态,用于未来获取协程的结果。
import asyncio
import time
async def my_task(seconds):
print('This task is taking {} seconds to complete'.format(seconds))
time.sleep(seconds)
return 'task finished' #协程返回的结果 用task.result()获取
if \_\_name__ == '\_\_main__':
my_event_loop = asyncio.get_event_loop()
try:
print('task creation started')
task_obj = my_event_loop.create_task(my_task(seconds=2))
print(task_obj)
my_event_loop.run_until_complete(task_obj)
print(task_obj)
finally:
my_event_loop.close()
print("Ths task's result was: {}".format(task_obj.result()))
>>>
task creation started
<Task pending coro=<my_task() running at E:/pythonreview/asynciotest.py:8>>
This task is taking 2 seconds to complete
<Task finished coro=<my_task() done, defined at E:/pythonreview/asynciotest.py:8> result='task finished'>
Ths task's result was: task finished
Task在协程执行前后的状态是不一样的。
绑定回调
add_done_callback(fn) 当future执行完毕的时候添加一个回调
async def my_task(seconds):
print('This task is taking {} seconds to complete'.format(seconds))
time.sleep(seconds)
return 'task finished'
def callback(flag,future):
print(flag)
print(future.result())
if \_\_name__ == '\ _\_main__':
my_event_loop = asyncio.get_event_loop()
try:
print('task creation started')
task_obj = my_event_loop.create_task(my_task(seconds=2))
task_obj.add_done_callback(functools.partial(callback,'niao'))
my_event_loop.run_until_complete(task_obj)
finally:
my_event_loop.close()
>>>>add_done_callback函数的源码
def add_done_callback(self, fn):
"""Add a callback to be run when the future becomes done.
The callback is called with a single argument - the future object. If
the future is already done when this is called, the callback is
scheduled with call_soon.
"""
if self._state != _PENDING:
self._loop.call_soon(fn, self) #self在最后
else:
self._callbacks.append(fn)
result = await future 和 result = yield from future
将协程挂起,直到future执行完毕,返回future的结果或者抛出异常
async def test():
print('haha')
time.sleep(1)
async def display_date(loop):
end_time = loop.time()+5.0
while True:
print(datetime.datetime.now())
if (loop.time()+1.0) >= end_time:
break
await asyncio.ensure_future(test())
loop = asyncio.get_event_loop()
loop.run_until_complete(display_date(loop))
loop.close()
>>>
2017-07-06 23:33:43.825266
haha
2017-07-06 23:33:44.825323
haha
2017-07-06 23:33:45.825381
haha
2017-07-06 23:33:46.825438
haha
2017-07-06 23:33:47.825495
async def test():
print('haha')
time.sleep(1)
@asyncio.coroutine #yield from future 则需要采用@asyncio.coroutine
def display_date(loop):
end_time = loop.time()+5.0
while True:
print(datetime.datetime.now())
if (loop.time()+1.0) >= end_time:
break
yield from asyncio.ensure_future(test())
loop = asyncio.get_event_loop()
loop.run_until_complete(display_date(loop))
loop.close()
>>>
2017-07-06 23:35:40.037913
haha
2017-07-06 23:35:41.037970
haha
2017-07-06 23:35:42.038028
haha
2017-07-06 23:35:43.038085
haha
2017-07-06 23:35:44.038142
haha
2017-07-06 23:35:45.038199
协程链

async def compute(x,y):
print("Compute %s + %s ..."%(x,y))
await asyncio.sleep(1.0)
return x+y
async def print_sum(x,y):
result = await compute(x,y) #这时候print_sum挂起,执行compute
print("%s + %s = %s"%(x,y,result))
loop = asyncio.get_event_loop()
loop.run_until_complete(print_sum(1,2))
loop.close()
网友评论