当 queue.get 在 greenlets 内部调用时(主 greenlet 除外)gevent queue 不会引发 Empty?

gevent queue does not raise Empty when queue.get invoked inside greenlets (other than the main greenlet)?

我是 gevent 的新手,我的问题甚至可能非常天真,但是当我 运行 遵循代码时,我得到队列空异常。

案例 1 有道理

import gevent
from gevent import monkey
monkey.patch_all()

q = gevent.queue.Queue(maxsize=10)

try:
    q.get(timeout=1)
except gevent.queue.Empty:
    print("main greenlet queue empty")

但是如果我运行跟随代码我没有得到任何超时并且代码永远不会调用任何异常并且我永远不会进入异常处理块,事实上代码甚至不会等待 1 秒来获取来自队列的数据。我只是立即执行显示的输出。

案例2

import gevent
from gevent import monkey
monkey.patch_all()

q = gevent.queue.Queue(maxsize=10)

def worker(idx):
    print("worker", idx)
    try:
        q.get(timeout=1)
    except gevent.queue.Empty:
        print("worker", idx, "queue empty")

workers = [gevent.spawn(worker, i) for i in range(1)]

这个输出:

worker 0

但是,如果我在主 greenlet 中调用 get 并在子 greenlet 和主 greenlet 中调用 queue.get,如下所示,行为现在变回正常。

案例3

import gevent
from gevent import monkey
monkey.patch_all()

q = gevent.queue.Queue(maxsize=10)

def worker(idx):
    print("worker", idx)
    try:
        q.get(timeout=1)
    except gevent.queue.Empty:
        print("worker", idx, "queue empty")

workers = [gevent.spawn(worker, i) for i in range(1)]

try:
    q.get(timeout=1)
except gevent.queue.Empty:
    print("main greenlet queue empty")

我得到以下输出。

worker 0
main greenlet queue empty
worker 0 queue empty

我不明白为什么情况 2 没有引发异常,有人可以向我解释我做错了什么吗?

我正在使用 python 3.7 和 gevent '21.1.2'

在你的第二种情况下,你正在启动 greenlets(之后解释器退出)。添加 joinall() 使您的代码等待生成的 greenlets 到 return:

q = gevent.queue.Queue(maxsize=10)

def worker(idx):
    print("worker", idx)
    try:
        q.get(timeout=1)
    except gevent.queue.Empty:
        print("worker", idx, "queue empty")


print(q.empty())
workers = [gevent.spawn(worker, i) for i in range(1)]
# waiting for them to finish, works as expected!
gevent.joinall(workers)

输出:

True
worker 0
worker 0 queue empty