在 Django 中使用 gevent 时遇到异常问题如何解决?

有个即时爬虫的需求,每一次请求过来,就去网站爬取多条数据,所以用到了 gevent.spawn,代码如下

 spawns =[]
 for param in param_list:
            spawns.append(gevent.spawn(s_search, param))
 gevent.joinall(spawns)

s_search 是具体的爬取的代码,第一次请求的时候正常,第二次请求异常,第三次又正常了,就这样正常一次,错误一次。异常如下:

  File "C:\Users\duanbingjie\PycharmProjects\IpProxy\IpProxy\IPrice.py", line 107, in get_price
    gevent.joinall(spawns)
  File "C:\python27\lib\site-packages\gevent\greenlet.py", line 649, in joinall
    return wait(greenlets, timeout=timeout, count=count)
  File "C:\python27\lib\site-packages\gevent\hub.py", line 1038, in wait
    return list(iwait(objects, timeout, count))
  File "C:\python27\lib\site-packages\gevent\hub.py", line 985, in iwait
    item = waiter.get()
  File "C:\python27\lib\site-packages\gevent\hub.py", line 939, in get
    Waiter.get(self)
  File "C:\python27\lib\site-packages\gevent\hub.py", line 899, in get
    return self.hub.switch()
  File "C:\python27\lib\site-packages\gevent\hub.py", line 630, in switch
    return RawGreenlet.switch(self)
LoopExit: ('This operation would block forever', <Hub at 0x987f030 select pending=0 ref=0>)

在 Django 中使用 gevent 时遇到异常问题如何解决?

8 回复

不要在 http 请求里直接使用线程(或 gevent 之类的东西),你应当把异步任务交给 celery 处理。


在Django里用gevent遇到问题,最常见的就是猴子补丁没打对或者打晚了。

关键点就一个:必须在所有其他导入和Django启动之前,最早打上猴子补丁

比如你的 manage.pyasgi.py(如果用ASGI)最开头应该这样写:

# manage.py 或 asgi.py 的第一行代码
import gevent.monkey
gevent.monkey.patch_all()

# 然后再导入其他模块
import os
import django
from django.core.wsgi import get_wsgi_application
# ... 其他代码

如果已经这样做了还报错,比如出现 “GreenletExit” 或数据库连接异常,那可能是某些库和gevent不兼容,可以尝试只patch特定的模块:

import gevent.monkey
gevent.monkey.patch_socket()
gevent.monkey.patch_ssl()
# 而不是 patch_all()

另外,如果用到了 Django 的同步中间件或视图,在 gevent 下可能阻塞,建议检查是否所有IO操作都是 gevent 友好的(比如用 gevent.sleep 而不是 time.sleep)。

总结:先确保猴子补丁在最前面执行。

没办法呀,http 请求要即时的返回数据

celery 也能阻塞调用,没毛病


既然要即使返回,那就没必要用 gevent。
gevent 本来就是用来处理异步的,既然要做成同步操作用 gevent 就没有意义。

用 gunicorn 的 gevent 模式起 django

我也遇到这个问题了,请问您是怎么解决的啊

没解决

回到顶部