Python异步编程概述
协程:不同于线程和进程,不是物理存在的,是一种逻辑线程,本质就是通过一个线程实现代码块之间相互切换
一般程序代码都是由上到下依次执行,而协程就摆脱了了这个设定
例如:
fun1()
fun2()
协程可以先执行fun2()再执行fun1()
现如今主流实现协程的方式为asyncio模块+async和await关键字,python3.5以后
import asyncio
async def load1():
print("下载第一张图片")
await asyncio.sleep(2)#遇到IO堵塞
print("第一张图片下载完成")
async def load2():
print("下载第二张图片")
await asyncio.sleep(2)#遇到IO堵塞
print("第二张图片下载完成")
if __name__ == '__main__':
loop=asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait([asyncio.ensure_future(load1()),asyncio.ensure_future(load2())]))
这里可以看到,当请求下载第一张图片后,图片开始下载这里线程就处于等待,于是便请求下载第二章图片
不是协程的话则会等待第一张图片下载完毕才会请求下载第二张图片
协程的意义:当一个线程执行一个协程中中遇到IO等待时间,线程不会等待,而是跳转到其余协程执行不会白白等待
asyncio组件
事件循环:一个死循环,给定一个任务列表,检测任务的状态,对于已经完成的任务就剔除,如果是可执行就执行,对于IO等待的就略过,直到所有任务执行完毕结束循环
#获取事件循环
loop=asyncio.get_event_loop()
#将任务列表放入事件循环,直到所有任务都完成
loop.run_until_complete(tasks)
协程函数:async修饰,例如async def fun()
协程对象:执行协程函数的对象,例如 res=fun()
await
await+可等待的对象(协程对象,Future,Task对象)
遇到await就是等待,不会再往下走了,必须等待到有返回值
Task
在事件循环中添加多个任务,创建task对象包裹协程可以让协程中加入事件循环中等待被执行调度
创建task对象的方式
asyncio.create_task(协程对象) #3.7之后才有
loop.create_task(协程对象)
loop.create_future(协程对象)
import asyncio
async def load1():
print("下载第一张图片")
await asyncio.sleep(2)#遇到IO堵塞
print("第一张图片下载完成")
async def load2():
print("下载第二张图片")
await asyncio.sleep(2)#遇到IO堵塞
print("第二张图片下载完成")
async def main():
tasks={
loop.create_task(load1()),
loop.create_task(load2())
}
#传入任务列表和最长等待时间,返回两个集合,为已完成任务和未完成任务
done,pending=await asyncio.wait(tasks,timeout=2)
print(done)
print(pending)
if __name__ == '__main__':
loop=asyncio.get_event_loop()
loop.run_until_complete(main())
loop.close()
Future
Task继承Future
ayncio常用方法
asyncio.create_task(coroutine)
:将协程转换为任务,并提交给事件循环进行调度。返回一个Task
对象,可以用于监控任务的状态和获取结果。
asyncio.gather(*coroutines_or_futures, loop=None, return_exceptions=False)
:并发运行多个协程或Future
对象,并等待它们全部完成。返回一个包含所有结果的列表。如果设置return_exceptions=True
,则在出现异常时也会将异常包含在结果列表中,而不会抛出异常。
asyncio.wait(coros, *, loop=None, timeout=None, return_when=ALL_COMPLETED)
:并发运行多个协程,并等待它们全部完成。返回两个Future
集合:一个包含已完成的任务,一个包含未完成的任务。return_when
参数用于指定何时返回结果,可以设置为FIRST_COMPLETED
、FIRST_EXCEPTION
或ALL_COMPLETED
。
asyncio.sleep(delay, result=None, *, loop=None)
:异步休眠一段时间,以毫秒为单位。可以用于在协程中模拟延迟。
asyncio.run(main(), *, debug=False)
:用于运行主协程。在 Python 3.7+ 版本中,可以使用此方法来运行异步代码。
asyncio.ensure_future(coro_or_future, *, loop=None)
:将协程或Future
对象转换为Task
对象,并提交给事件循环进行调度。
asyncio.open_connection(host=None, port=None, *, loop=None, limit=None, **kwds)
:创建一个异步的 TCP 连接。返回一个(reader, writer)
的元组,分别用于读取和写入数据。
asyncio.start_server(client_connected_cb, host=None, port=None, *, loop=None, limit=None, **kwds)
:创建一个异步的 TCP 服务器。可以指定一个回调函数client_connected_cb
来处理客户端连接。
asyncio.start_tls(transport, protocol, sslcontext, server_side=None, server_hostname=None, ssl_handshake_timeout=None)
:将一个已有的异步传输对象(如 TCP 连接)升级为 TLS/SSL 安全传输层。
asyncio.open_unix_connection(path=None, *, loop=None, limit=None, **kwds)
:创建一个异步的 Unix 域套接字连接。