【问题标题】:gevent, requests and unhandled exceptiongevent、请求和未处理的异常
【发布时间】:2013-03-20 19:26:07
【问题描述】:

我有代码:

import gevent
import gevent.monkey; gevent.monkey.patch_all()
import requests

def func():
    try:
        requests.get('http://unavailable-host/')
    except:
        pass

def main():
    jobs = [gevent.spawn(func) for i in xrange(10)]
    gevent.joinall(jobs)

if __name__ == '__main__':
    main()

这个脚本通常没有输出。但有时(在 5 次中的 1 次中)我会收到以下消息:

Unhandled exception in thread started by
sys.excepthook is missing
lost sys.stderr

解释一下,为什么会发生这种情况,什么是正确的解决方案?另外,如果我添加

gevent.sleep(1)

之后

gevent.joinall(jobs)

脚本总是没有输出,一切正常。

【问题讨论】:

    标签: python gevent


    【解决方案1】:

    编辑:

    这似乎与在主程序已经退出后尝试执行某些操作(例如打印到 stdout/stderr)的线程有关。

    参考Python Bugs: issue1722344

    和 Martijn Pieters 在a similar SO question 的回答中的评论:

    确实,产生错误是因为python正在退出并且还有一个线程处于活动状态。

    之前的(完全不正确的)答案:

    您正在经历的是monkey_patch 的不那么有趣的副作用之一。

    requests 使用socket 作为通过 Internet 将数据传输到某个地址的底层机制。 gevent.monkey.patch_all() 将 stdlib socket 替换为 gevent.socket,这是一个异步(非阻塞)套接字,因此在代码深处的某个地方(我的猜测是 http.clienturllib 使用,它依次由requests 使用),其中发出sock.recv(X) 命令,其中代码预计会阻塞,直到收到X 字节或套接字关闭,而是因为套接字已被gevent.socket 替换,它立即返回只有当前流缓冲区中的字节数,代码中断。

    但是,在您的情况下,简单的解决方案是简单地使用 grequests,这是为使用 gevent 构建的请求(实际上,它自己执行 monkey_patch。)

    【讨论】:

    • 当我使用 grequests 时,我在控制台中收到 ConnectionError。 Grequest 对我来说不是很好的变体,因为我想以同步风格编写代码并发送不同请求的链。是否有任何其他变体可以解决 未处理的异常 问题而不是 gevent.sleep(1)?
    • @Chrome 嗯。我懂了。在第二次检查中,它看起来与 gevent/stdlib-socket 问题无关。请参阅编辑以获取新答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-04
    • 1970-01-01
    • 1970-01-01
    • 2014-08-05
    • 2020-06-09
    • 1970-01-01
    相关资源
    最近更新 更多