各位大佬,小弟使用 gevent 遇到了 loopexit 的错误

2020-11-17 17:00:45 +08:00
 xiangyuhahah

我这边遇到一个问题,使用 gevent 的时候,报了 loopexit 的错误。

import random
from Queue import Empty
import gevent
from gevent.queue import *

import gevent.monkey
gevent.monkey.patch_all()


q = Queue()
workers = []


def do_work(wid, value):
    gevent.sleep(random.randint(0,2))
    print 'Task', value, 'done', wid
    return


def worker(wid):
    while True:
        try:
            item = q.get()
            if item:
                do_work(wid, item)
        except StopIteration:
            break
        except Empty:
            break


def producer():
    for i in range(4):
        workers.append(gevent.spawn(worker, random.randint(1, 888888)))

    for item in range(1, 9):
        q.put(item)


producer()
gevent.joinall(workers)

我查了网上的资料,看了 gevent 的原理,但是没怎么看明白。网上主流的解释是任务流已经消费完了,协程都在做 waiter 的操作,导致 gevent 的 joinall 失败了。我没有理解这个过程。现在的我的解决办法是,消费完任务之后协程会报空的错误,捕捉一下就退出协程。但是我感觉这样只是掩盖了问题,没有解决问题。

item = q.get() >>item = q.get(block=False)

各位大佬怎么理解 loopexit ?

1569 次点击
所在节点    Python
2 条回复
cz5424
2020-11-18 00:05:12 +08:00
感觉是 Queue(),如果想要多线程多进程和协程,一般会避免全局变量
catxo
2020-11-18 09:50:59 +08:00
你的 worker 是一个循环,没有退出条件
一般都是判断 item 为空作为退出条件
```python
item = q.get()
if not item:
break
do_work(wid, item)
```

producer 里面,加上
```python
for _ in range(4):
q.put(None)
```

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/726289

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX