python asyncio模块

本文详细介绍了Python的asyncio模块,包括事件循环的创建与执行、协程的概念及示例、Future与Task对象的区别、回调的使用方法、任务的聚合以及队伍的管理,是理解Python异步编程的重要参考资料。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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是一个用于通知异步函数状态的对象。包括函数的状态,函数的结果或者当函数引发异常时,返回对应的异常和回溯。

Future是一个独立的对象,并不依赖正在执行的函数。该对象仅仅用于存储状态和结果信息。

  • Task对象

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())
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值