简体   繁体   English

gevent,请求和未处理的异常

[英]gevent, requests and unhandled exception

I have code: 我有代码:

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()

This script usually nothing output. 该脚本通常没有输出。 But sometimes (in 1 of 5 runs) i get this message: 但有时(在5次运行中有1次)我收到此消息:

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

Explain me, why this happen, and what is right solution? 请解释一下,为什么会这样,什么是正确的解决方案? Also, if I add 另外,如果我添加

gevent.sleep(1)

after

gevent.joinall(jobs)

script always nothing output, all is ok. 脚本始终无输出,一切正常。

Edit: 编辑:

This seems like it has to do with a thread trying to do stuff (like print to stdout/stderr) after the main program has already exited. 在主程序退出后,这似乎与尝试执行处理(例如打印到stdout / stderr)的线程有关。

See Python Bugs: issue1722344 for reference, 有关参考,请参见Python错误:issue1722344

and Martijn Pieters's comment in this answer to a similar SO question : 和Martijn Pieters在此答案中对类似SO问题的评论:

Indeed, the error is generated because python is exiting and there is still a thread active. 确实,由于python正在退出并且仍然有活动的线程而产生了错误。

Previous (and completely incorrect) answer: 先前的答案(完全不正确):

What you are experiencing is one of the not-so-fun side effects of monkey_patch . 您正在体验的是monkey_patch有趣的副作用之一。

requests uses socket as the underlying mechanism for transferring data across the internet to some address. requestssocket用作将数据通过Internet传输到某个地址的基础机制。 gevent.monkey.patch_all() replaces the stdlib socket with gevent.socket , which is an asynchronous (non-blocking) socket, and so when somewhere deep within the code (my guess goes to http.client which is used by urllib , which is in turn used by requests ), where a sock.recv(X) command is made, where the code is expected to block until X bytes are received or the socket is closed , and instead, because the socket has been replaced by gevent.socket , which returns immediately with only as many bytes as are currently in the stream buffer , the code breaks. gevent.monkey.patch_all()替换STDLIB socketgevent.socket ,它是一个异步(非阻塞)插座,并因此当某处的代码内的深处(我的猜测去http.client其中使用由urllib ,这依次由requests所使用),在该处执行sock.recv(X)命令,在接收到X个字节或关闭套接字之前 ,代码将一直阻塞 ,因为套接字已被gevent.socket替换gevent.socket ,它返回的字节数立即与流缓冲区中当前字节数立即返回 ,代码中断。

The easy solution in your case, however, is to simply use grequests , which is requests built to use gevent (and which, in fact, does its own monkey_patch.) 但是,在您的情况下,简单的解决方案是只使用grequests ,这是使用gevent构建的请求(实际上,它是自己做的monkey_patch。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM