昨天在聚会上有人告诉我,如果回调在Node.js中引发异常,它将使整个进程崩溃。但是如果一个greenlet在Gevent中抛出一个未被捕获的异常,它只会崩溃greenlet。
我没有Gevent的经验,我想知道这是否属实。
答案 0 :(得分:1)
这是一个exmaple代码,显示当greenlet抛出未捕获的excpetion时,整个过程不会崩溃。代码为here,输出如下:
Traceback (most recent call last):
File "/usr/lib/python2.7/site-packages/gevent/greenlet.py", line 327, in run
result = self._run(*self.args, **self.kwargs)
File "test_exception_greenlet.py", line 31, in _fail
raise Exception('you fail')
Exception: you fail
<Greenlet at 0x8b5cc5c: <bound method TestgException._fail of <__main__.TestgException object at 0x8bd4a0c>>> failed with Exception
win ready? True
fail ready? True
win successful()? True
fail successful()? False
exception: Exception('you fail',)
使用gevent
实现并发任务时,应生成一些coroutines
,即greenlets
,然后主线程应切换到名为greenlet > hub 然后循环发生在greenlets
之间。工作流程如下:
主线程 - &gt;一个greenlet - &gt; hub greenlet - &gt;绿色 - &gt; hub greenlet - &gt;绿色 - &gt; ... - &gt;一些greenlet - &gt;主线程 - &gt; ......(可能再次进入循环)
从这里开始,您应该知道greenlet如何在内部运行。 greenlet是Greenlet
的实例。当greenlet运行时,它会调用其run()
方法。以下是run()
类中Greenlet
的源代码:
def run(self):
try:
if self._start_event is None:
self._start_event = _dummy_event
else:
self._start_event.stop()
try:
result = self._run(*self.args, **self.kwargs)
except:
self._report_error(sys.exc_info())
return
self._report_result(result)
finally:
self.__dict__.pop('_run', None)
self.__dict__.pop('args', None)
self.__dict__.pop('kwargs', None)
此处的_run()
方法是与要作为greenlet运行的任务的绑定。从这里你可以看到,如果发生异常,它将被_report_error()
方法捕获并报告。通过阅读由前者调用的_report_error()
和_report_result()
的源代码,您知道它捕获了异常并且只是greenlet死了而不是整个过程。当greenlet引发未捕获的异常时,它会死亡,而hub
greenlet将不再安排它。
如果您对Greenlet
的实施感兴趣,请参阅source code
答案 1 :(得分:1)
Node.js应用程序在未捕获的异常时崩溃了吗?是。例如,参见http://shapeshed.com/uncaught-exceptions-in-node/
Gevent greenlets中未被捕获的异常只会降低有问题的greenlet吗?是。例如,参见http://www.gevent.org/gevent.html,特别是Greenlet.exception
“如果greenlet已经完成了错误,则保存函数引发的异常实例”,从而使异常实例可用于进程的其余部分,但不会崩溃。