深入解析 Python 中 yield 实现异步协作的原理
本文深入解析 Python 中 yield 关键字在异步编程中的应用。通过剖析生成器的 send() 方法,详细阐述 yield 如何挂起与恢复执行、接收参数及返回值,从而模拟异步协作流程。同时结合简单调度器示例,解释基于事件循环的异步模型运行机制,帮助开发者理解 Python 异步操作的底层逻辑。
初学 Python 时,yield 关键字往往令人感到困惑。理解其核心作用对于掌握高级特性至关重要,主要功能包括:
① 返回当前计算结果;② 接收来自调用者通过 send() 传递的参数。
为了更清晰地理解这一机制,我们分析以下代码示例:
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
def consumer():
r = ''
while True:
n = yield r
print("[Consumer] n = %d" %n)
if not n:
return
print("[Consumer] consuming %s..." %n)
r = '200 OK'
def produce(c):
c.send(None)
h = 0
while h < 5:
h = h + 1
print("[Producer] producing %d..." %h)
s = c.send(h)
print("[Producer] consumer return: %s" %s)
c.close()
c = consumer() #创建一个生成器
produce(c) #在该函数中,调用生成器的send()方法

结合程序的执行流程,可以得出以下运行逻辑:
第一步:
在 produce(c) 函数内部,首先调用 c.send(None) 来启动生成器。此时程序执行至 yield 语句处暂停。随后,produce() 函数继续执行后续代码。从运行结果可以看出,确实打印了 [Produce] producing 1 …。当程序执行到 c.send(h) 时,通过 yield 将参数(h = 1)传递给 consumer() 函数,从而进入 consumer() 的执行上下文。
第二步:
yield 将传递的参数(h=1)赋值给 consumer() 函数中的变量 n,并接着上一次暂停的位置继续执行。此时打印出 [Consumer] n = 1,[Consumer] consuming 1…。在 consumer() 函数内部,变量 r 被赋值为 '200 OK'。接着循环遇到 yield,consumer() 函数再次暂停,并将变量 r 的值返回。此时控制权交还,程序重新进入 produce(c) 函数继续执行。
第三步:
produce(c) 函数接着从第一步中 c.send(h) 的位置继续向下执行,打印出 [Producer] consumer return: 200 OK。随后进入下一轮循环,打印 [Producer] producing 2…,并再次调用 c.send(h) …。如此循环往复,回到第一步的逻辑,直到满足终止条件。
补充知识:Python asyncio 模型中的事件循环机制
异步编程的核心基础是事件循环。
简单来说,事件循环的工作流程如下:
1. 将待执行的函数或任务放入队列;
2. 从队列中取出函数并执行;
3. 检查该函数是否还需要继续执行(例如是否有新的任务生成);
4. 若需继续,则重复第一步。
以下是一个简单的示例说明:
"""
1.yield 挂起当前函数.
2.使用调度器循环
3.使用next唤醒此函数继续执行
"""
def f1():
for i in range(3):
print('f1 %d'%i)
yield
def f2():
for i in range(5):
print('f2 %d' %i)
yield
def f3():
for i in range(10):
print('f3 %d'%i)
yield
#模拟一个调度器
task_q = collections.deque((f1(),f2(),f3()))
#让调度器调度这些生成器们
while task_q:
task = task_q.popleft() #弹出首个生成器
try:
next(task) #执行,如果没有异常证明此生成器还没执行完成,可以继续放入队列中
task_q.append(task) #执行完成后,把任务继续添加到队列中.
time.sleep(0.5)
except StopIteration as ex:
pass
以上关于 Python 中由 yield 实现异步操作的解析就是全部内容,希望能对大家理解生成器与异步协作有所帮助,欢迎参考与支持。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













