定義
- asyncio模塊提供了圍繞event loop的框架福压。event_loop 事件循環(huán)等待滿足某事件的發(fā)生栋操,然后在事件上調(diào)取相應(yīng)的函數(shù)僵腺『獠椋“when event A happens, react with function B”
- coroutine 協(xié)程 是一個(gè)特殊的函數(shù)呵晚,當(dāng)調(diào)用時(shí)不會(huì)立即執(zhí)行函數(shù)蜘腌,而是會(huì)返回一個(gè)協(xié)程對(duì)象。你可以把coroutine對(duì)象傳到event loop中饵隙,有event loop選擇是立即調(diào)用還是推后執(zhí)行撮珠。
- future 代表將來執(zhí)行或沒有執(zhí)行的任務(wù)的結(jié)果。event loop能夠件事future對(duì)象并且等到它執(zhí)行金矛。
- task 對(duì)coroutine的封裝芯急,是future的子類
async 和@asyncio.coroutine
用來定義一個(gè)協(xié)程。
import asyncio
@asyncio.coroutine
def my_coro():
yield from func()
>>>>
async def my_coro():
await func()
>>>兩種定義協(xié)程的方式
例如
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
協(xié)程換成如下定義也行
async def my_coro():
ran = random.randint(1,1000)
print(ran)
函數(shù)調(diào)度
call_soon(callback, *args)
call_soon_threadsafe(callback, *args)
安排一個(gè)回調(diào)一遍盡快調(diào)用
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執(zhí)行event_handle
基于event loop的記時(shí)
current_time = loop.time()
Tasks
所謂task對(duì)象是Future類的子類驶俊。保存了協(xié)程運(yùn)行后的狀態(tài)娶耍,用于未來獲取協(xié)程的結(jié)果。
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' #協(xié)程返回的結(jié)果 用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在協(xié)程執(zhí)行前后的狀態(tài)是不一樣的饼酿。
綁定回調(diào)
add_done_callback(fn) 當(dāng)future執(zhí)行完畢的時(shí)候添加一個(gè)回調(diào)
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函數(shù)的源碼
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
將協(xié)程掛起榕酒,直到future執(zhí)行完畢胚膊,返回future的結(jié)果或者拋出異常
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
協(xié)程鏈
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) #這時(shí)候print_sum掛起,執(zhí)行compute
print("%s + %s = %s"%(x,y,result))
loop = asyncio.get_event_loop()
loop.run_until_complete(print_sum(1,2))
loop.close()