摘要
因为AI的爆火,python的使用越来越广泛,python的协程也越来越受到关注,本文主要记录一下python协程的相关知识。
协程
在Python中,协程是一种特殊的函数,它能暂停其执行并在需要时恢复。与传统的线程相比,协程是轻量级的,它们在单个线程内部进行切换,这减少了上下文切换的成本和复杂性。协程是异步编程的一部分,特别适合于I/O密集型任务和高并发场景。
协程的使用
协程的使用需要用到async和await关键字,async用于定义一个协程,await用于挂起一个协程,等待其执行完成。1
2
3
4
5
6
7
8import asyncio
async def hello_world():
print("Hello World")
await asyncio.sleep(1)
print("Hello again")
asyncio.run(hello_world())
上面的代码中,asyncio.run用于运行一个协程,asyncio.sleep用于挂起一个协程,等待其执行完成。hello_world是一个coruntine function,它的返回值是一个coruntine object,coruntine object是awaitable的,awaitable是可以使用await关键字挂起的对象,awaitable包括coruntine object、Future、Task等。
协程的执行
协程的执行需要用到asyncio模块,asyncio模块提供了一些函数用于协程的执行,如asyncio.run、asyncio.create_task、asyncio.gather等。
asyncio.run
asyncio.run用于运行一个协程,它会创建一个事件循环并在协程执行完成后关闭事件循环。1
2
3
4
5
6
7
8import asyncio
async def main():
print('hello')
await asyncio.sleep(1)
print('world')
asyncio.run(main())
asyncio.create_task
asyncio.create_task用于创建一个任务,它会将协程封装成一个Task对象,Task对象是Future的子类,它表示一个异步操作的最终结果。Task对象会被asyncio调度执行。1
2
3
4
5
6
7
8import asyncio
async def main():
print('hello')
await asyncio.sleep(1)
print('world')
asyncio.create_task(main())
asyncio.gather
asyncio.gather用于并发运行多个协程,它会将多个协程封装成一个Future对象,Future对象是Task的父类,它表示一个异步操作的最终结果。Future对象会被asyncio调度执行。1
2
3
4
5
6
7
8import asyncio
async def main():
print('hello')
await asyncio.sleep(1)
print('world')
asyncio.gather(main())
await和asyncio.create_task的区别,await是直接在事件循环里面执行,而asyncio.create_task是创建一个task,然后将task加入到事件循环中。所以task要等到下一次事件循环才会执行。
同步方法的异步调用
在协程中调用同步方法会阻塞协程的执行,可以使用run_in_executor方法将同步方法封装成一个协程,然后在协程中调用。1
2
3
4
5
6
7
8
9import asyncio
def sync_func():
print('sync_func')
async def main():
await asyncio.get_running_loop().run_in_executor(None, sync_func)
asyncio.run(main())
在python中一般I/O操作都会释放GIL,所以在协程中调用同步方法不会阻塞协程的执行。