1.事件循环
大多数异步程序实现异步的基本机制是通过在后台执行的事件循环。当有代码需要执行时,这些代码才会被注册到事件循环中
摘自:Python高级编程
在大多数情况下,并不需要创建一个事件循环对象。可以通过asyncio.get_event_loop()函数返回一个BaseEventLoop对象。
import asyncio
#获取一个事件循环对象(BaseEventLoop对象)
loop=asyncio.get_event_loop()
#事件死循环
loop.run_forever()
import asyncio
import functools
#获取一个事件循环对象(BaseEventLoop对象)
loop=asyncio.get_event_loop()
def stop_loop(loop):
print('Stopping loop')
#用于停止循环
loop.stop()
def hello_world():
print('hello world')
'''
call_soon用于将任务注册到循环中
未使用偏函数的任务注册
loop.call_soon(print,'hello world')
loop.call_soon(stop_loop,loop)
使用偏函数的任务注册
'''
loop.call_soon(functools.partial(print,'Hello World'))
loop.call_soon(functools.partial(stop_loop,loop))
#执行循环
loop.run_forever()
#注册晚一点被调用的任务,时间单位是秒
loop.call_later(10,hello_world)
loop.call_later(20,functools.partial(stop_loop,loop))
import asyncio
#装饰器的作用是将普通的Python函数转换为一个协程
@asyncio.coroutine
def trivial():
return 'Hello World'
loop=asyncio.get_event_loop()
#任务注册,并在任务结束前执行循环
ret=loop.run_until_complete(trivial())
print(ret)
import asyncio
import threading
def run_loop_forever_in_background(loop):
def thread_fun(l):
asyncio.set_event_loop(l)
l.run_forever()
thread=threading.Thread(target=thread_fun,args=(loop,))
thread.start()
return thread
loop=asyncio.get_event_loop()
print(run_loop_forever_in_background(loop))
print(loop.is_running())
2.协程
在asyncio中使用的大多数函数是协程(coroutines)。协程是一种被设计用于事件循环中执行的特殊函数。如果创建了协程但并未执行,将会在日志中记录一个错误。
import asyncio
@asyncio.coroutine
def coro_sum(*args):
answer=0
for i in args:
answer+=i
return answer
loop=asyncio.get_event_loop()
ret=loop.run_until_complete(coro_sum(1,2,3,4,5,6))
print(ret)
import asyncio
@asyncio.coroutine
def nested(*args):
print("The 'nested' function ran with args:",args)
return [i+1 for i in args]
@asyncio.coroutine
def outer(*args):
print("The 'outer' function ran with args:",args)
'''
使用yield from让一个协程可以执行另一个协程
当outer协程遇到yield from语句时挂起,
nested协程被放入事件循环并执行,
nested协程执行完后,在继续执行outer协程
'''
answer=yield from nested(*[i*2 for i in args])
return answer
loop=asyncio.get_event_loop()
ret=loop.run_until_complete(outer(2,3,5,8))
print(ret)
3.Future对象与Task对象
本质上讲,Future是一个用于通知异步函数状态的对象。包括函数的状态,函数的结果或者当函数引发异常时,返回对应的异常和回溯。
Future是一个独立的对象,并不依赖正在执行的函数。该对象仅仅用于存储状态和结果信息。
Task对象是Future对象的子类,协程会被一个Task对象包装。Task对象的任务是存储结果并为yield from语句提供值。
``
import asyncio
@asyncio.coroutine
def make_tea(variety):
print('Now making {0} tea'.format(variety))
#结束循环
asyncio.get_event_loop().stop()
return '{0} tea'.format(variety)
'''
使用asyncio.ensure_future方法,将协程放入事件循环,
并返回对应的Task对象
task=asyncio.async(make_tea('chamomile'))
'''
task=asyncio.ensure_future(make_tea('chamomile'))
loop=asyncio.get_event_loop()
loop.run_forever()
#返回bool值,判断task是否执行
print(task.done())
#返回task对象的存储结果
print(task.result())
4.回调
回调就是一个在Future完成后执行的一个函数(或协程),该函数接受Future作为参数
可以使用对象的add_done_callback方法将一个回调添加到任何Future对象。
import asyncio
loop=asyncio.get_event_loop()
@asyncio.coroutine
def make_tea(variety):
print('Now making {0} tea'.format(variety))
return '{0} tea'.format(variety)
def confirm_tea(future):
print('The {0} is made.'.format(future.result()))
task=asyncio.ensure_future(make_tea('green'))
'''
将confirm_tea函数注册到Future对象中
将Future对象作为参数传给confirm_tea函数
'''
task.add_done_callback(confirm_tea)
loop.run_until_complete(task)
import functools
import asyncio
loop=asyncio.get_event_loop()
@asyncio.coroutine
def make_tea(variety):
print('Now making {0} tea'.format(variety))
return '{0} tea'.format(variety)
#Future对象附加到位置参数列表的结尾处
def confirm_tea(ingredient,future):
print('Now adding {0} to the {1}'.format(ingredient,future.result()))
task=asyncio.ensure_future(make_tea('green'))
task.add_done_callback(functools.partial(confirm_tea,'honey'))
loop.run_until_complete(task)
5.任务聚合
asyncio未聚集任务目的提供的第一种机制是通过gather函数。
``
import asyncio
loop=asyncio.get_event_loop()
@asyncio.coroutine
def make_tea(variety):
print('Now making {0} tea'.format(variety))
return '{0} tea'.format(variety)
def mix(future):
print('Mixing the {0} together'.format(' and '.join(future.result())))
#聚集任务
meta_task=asyncio.gather(
make_tea('chamonile'),
make_tea('green'),
make_tea('herbal')
)
#添加回调
meta_task.add_done_callback(mix)
ret=loop.run_until_complete(meta_task)
print(ret)
asyncio模块提供的另一个工具是内置的wait协程。
import asyncio
loop=asyncio.get_event_loop()
@asyncio.coroutine
def make_tea(variety):
print('Now making {0} tea'.format(variety))
return '{0} tea'.format(variety)
'''
asyncio.wait方法的其他参数
超时:timeout
coro=asyncio.wait([asyncio.sleep(5),asyncio.sleep(1)],timeout=3)
等待任意任务:return_when
coro=asyncio.wait([asyncio.sleep(3),asyncio.sleep(2),asyncio.sleep(1)],return_when=asyncio.FIRST_COMPLETED)
等待异常:return_when
coro=asyncio.wait([asyncio.sleep(1),asyncio.sleep(2)],return_when=asyncio.FIRST_EXCEPTION)
'''
#参数为一个列表
coro=asyncio.wait([make_tea('chamomile'),make_tea('green')])
loop.run_until_complete(coro)
6.队伍
import asyncio
#设置队伍最大值
queue=asyncio.Queue(maxsize=5)
#立即从队伍中添加一项
queue.put_nowait('foo')
#获取队伍的长度
print(queue.qsize())
'''
队伍为空不引发异常,耐心等待队伍添加数据:
queue.get()
'''
#立即从队伍中移除一项
print(queue.get_nowait())
print(queue.qsize())