Python协程

记录一下python协程相关的知识

摘要

因为AI的爆火,python的使用越来越广泛,python的协程也越来越受到关注,本文主要记录一下python协程的相关知识。

协程

在Python中,协程是一种特殊的函数,它能暂停其执行并在需要时恢复。与传统的线程相比,协程是轻量级的,它们在单个线程内部进行切换,这减少了上下文切换的成本和复杂性。协程是异步编程的一部分,特别适合于I/O密集型任务和高并发场景。

协程的使用

协程的使用需要用到asyncawait关键字,async用于定义一个协程,await用于挂起一个协程,等待其执行完成。

1
2
3
4
5
6
7
8
import 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 objectcoruntine objectawaitable的,awaitable是可以使用await关键字挂起的对象,awaitable包括coruntine objectFutureTask等。

协程的执行

协程的执行需要用到asyncio模块,asyncio模块提供了一些函数用于协程的执行,如asyncio.runasyncio.create_taskasyncio.gather等。

asyncio.run

asyncio.run用于运行一个协程,它会创建一个事件循环并在协程执行完成后关闭事件循环。

1
2
3
4
5
6
7
8
import 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
8
import 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
8
import 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
9
import 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,所以在协程中调用同步方法不会阻塞协程的执行。