asyncio学习

定义

  • asyncio模块提供了围绕event loop的框架。event_loop 事件循环等待满足某事件的发生,然后在事件上调取相应的函数。“when event A happens, react with function B”
  • coroutine 协程 是一个特殊的函数,当调用时不会立即执行函数,而是会返回一个协程对象。你可以把coroutine对象传到event loop中,有event loop选择是立即调用还是推后执行。
  • future 代表将来执行或没有执行的任务的结果。event loop能够件事future对象并且等到它执行。
  • task 对coroutine的封装,是future的子类

async 和@asyncio.coroutine

用来定义一个协程。

import asyncio
@asyncio.coroutine
def my_coro():
    yield from func()
>>>>
async def my_coro():
    await func()
>>>两种定义协程的方式

例如

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
>
This task is taking 2 seconds to complete
 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

协程链

asyncio学习_第1张图片
image.png
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()

你可能感兴趣的:(asyncio学习)