You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python 2.7中如何在同一事件循环中遍历两个异步生成器

如何在Python 2.7中同时消费两个生成器(或ZeroMQ订阅者)

这个问题我之前也碰到过,你原来的写法确实只会一直输出1——因为生成器对象在布尔判断里属于真值,gen_one() or gen_two()会直接返回第一个生成器,循环自然只会迭代它,完全碰不到第二个生成器。

要实现按各自的产出顺序消费,得用多路复用或者线程+队列的思路,下面分场景给你具体方案:

方案一:针对实际ZeroMQ订阅者场景(推荐)

ZeroMQ的套接字支持用select模块做IO多路复用,这是最适合的方案,不需要额外线程,效率也高。我们可以把两个订阅者套接字注册到可读监听列表里,哪个有数据就处理哪个:

import zmq
import select

context = zmq.Context()

# 初始化第一个订阅者
sub1 = context.socket(zmq.SUB)
sub1.connect("tcp://localhost:5555")
sub1.setsockopt(zmq.SUBSCRIBE, "")  # 订阅所有消息

# 初始化第二个订阅者
sub2 = context.socket(zmq.SUB)
sub2.connect("tcp://localhost:5556")
sub2.setsockopt(zmq.SUBSCRIBE, "")

# 要监听的可读套接字集合
read_sockets = [sub1, sub2]

while True:
    # 阻塞等待至少一个套接字可读
    readable, _, _ = select.select(read_sockets, [], [])
    for sock in readable:
        # 读取并处理消息
        data = sock.recv()
        print(data)

这样不管哪个订阅者先收到消息,都会被及时处理,完全符合你期望的“谁先就绪谁先输出”的逻辑。

方案二:针对生成器模拟场景

如果只是用生成器模拟这个逻辑,因为生成器的yield是同步阻塞的,我们可以用线程把每个生成器的产出放到线程安全的队列里,主线程从队列取数据即可:

import time
import threading
from Queue import Queue

def gen_one(q):
    while True:
        q.put(1)
        time.sleep(1)

def gen_two(q):
    while True:
        q.put(2)
        time.sleep(1.3)

# 创建线程安全的队列
msg_queue = Queue()

# 启动两个线程分别运行生成器
t1 = threading.Thread(target=gen_one, args=(msg_queue,))
t2 = threading.Thread(target=gen_two, args=(msg_queue,))
# 设置为守护线程,主线程退出时自动结束
t1.daemon = True
t2.daemon = True
t1.start()
t2.start()

# 主线程持续从队列取数据输出
while True:
    item = msg_queue.get()
    print(item)

运行这段代码,输出就会和你期望的一致:1、2、1、2、1、2、1、1、2...

补充:为什么原代码失效?

再啰嗦一句,你原代码里的for a in gen_one() or gen_two(),gen_one()返回的是一个非空的生成器对象,在Python的布尔判断中会被视为True,所以or运算符直接返回第一个生成器,循环只会迭代它,自然一直输出1,完全不会触发第二个生成器的执行。

内容的提问来源于stack exchange,提问作者sagism

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 06:47:22