• 周三. 10 月 16th, 2024

Python 协程用法详解

城主

12 月 30, 2022 ,

协程是一种轻量级的用于在一个线程中实现并发执行多个任务的机制。它允许在执行过程中暂停和恢复函数的执行,而无需使用线程或进程。

协程的工作原理是通过使用一个特殊的关键字 yield 来暂停函数的执行,然后通过使用 send() 方法来恢复执行。这使得协程可以在执行过程中交换数据,并且可以在执行过程中被外部程序控制。

举个例子,下面是一个简单的协程,它在执行过程中交换数据:





def my_coroutine():
    while True:
        received = yield
        print("Received:", received)

# 创建协程对象
co = my_coroutine()

# 启动协程
next(co)

# 发送数据到协程并恢复执行
co.send("Hello, world!")

协程可以用于实现异步 I/O 操作,例如网络通信和文件 I/O。它们可以极大地提高程序的效率,因为它们允许程序在等待 I/O 操作完成时暂停执行,而不需要使用线程。

要使用协程,需要在 Python 3.5 及更高版本中使用 asyncawait 关键字。

在 Python 中,你可以使用 asyncawait 关键字来实现异步编程。这些关键字可以用于协程函数,以便在执行过程中暂停和恢复函数的执行。

下面是一个使用协程的简单示例,它在等待网络连接时执行:





import asyncio

async def connect_to_server():
    # 等待网络连接
    await asyncio.sleep(1)
    print("Connected to server!")

async def main():
    # 等待连接到服务器
    await connect_to_server()
    print("Task completed!")

# 运行协程
asyncio.run(main())

上面的代码会在连接到服务器之后打印 “Connected to server!” 和 “Task completed!”。

如果你想要在协程执行过程中重复执行某个操作,可以使用循环。例如,下面的代码在协程执行过程中重复打印 “Hello, world!”:





import asyncio

async def repeat_hello():
    while True:
        print("Hello, world!")
        await asyncio.sleep(1)

async def main():
    # 在协程执行过程中重复打印 "Hello, world!"
    await repeat_hello()

asyncio.run(main())

上面的代码会在协程执行过程中每隔 1 秒打印一次 “Hello, world!”。

阅读  Python 可视化详细用法

如果你想要在协程执行过程中暂停和恢复函数的执行,可以使用 asyncio.Event 对象。这个对象可以用来控制协程的执行,当事件被设置为真时,协程会继续执行,否则会暂停。

下面是一个示例,它在协程执行过程中暂停和恢复函数的执行:





import asyncio

async def my_coroutine(event):
    while not event.is_set():
        print("Waiting for event...")
        await asyncio.sleep(1)
    print("Event set, continuing...")

async def main():
    # 创建事件对象
    event = asyncio.Event()

    # 启动协程
    co = my_coroutine(event)
    await co

    # 等待 3 秒
    print("Waiting 3 seconds...")
    await asyncio.sleep(3)

    # 设置事件,协程继续执行
    event.set()

asyncio.run(main())

上面的代码会在协程执行过程中每隔 1 秒打印一次 “Waiting for event…”,然后在等待 3 秒后设置事件,使协程继续执行,最后打印 “Event set, continuing…”。

注意,协程是在事件被设置之前就已经启动的,所以在协程内部使用事件时,应该在协程的最开始就先等待事件。这样,协程就不会在事件被设置之前立即执行,从而避免了重复执行的情况。