3

eventlet.GreenPool.spawnを使用していくつかのタスクを実行し、すべてのgreanthreadsが終了するのを待ちます。例外が発生することはわかっています-その例外をキャッチしてメインスレッドにスローするにはどうすればよいですか?簡単だと思いますが、何かが足りません。

これが例です(失敗し、成功したいです)

import unittest
import eventlet


def broken_fetch(url):
    print " Raising exception "
    raise RuntimeError


class TestPool(unittest.TestCase):

    def test_error_is_bubbled_up(self):
        with self.assertRaises(RuntimeError):
            pool = eventlet.GreenPool(100)
            urls = ['http://google.com/', 'http://example.com/']
            for url in urls:
                pool.spawn(broken_fetch, url)
            pool.waitall()

if __name__ == '__main__':
    unittest.main()

そしてそれは出力です:

> python errors.py
Raising exception 
Traceback (most recent call last):
File "/usr/local/lib/python2.7/site-packages/eventlet/hubs/hub.py", line 336, in fire_timers
    timer()
File "/usr/local/lib/python2.7/site-packages/eventlet/hubs/timer.py", line 56, in __call__
    cb(*args, **kw)
File "/usr/local/lib/python2.7/site-packages/eventlet/greenthread.py", line 192, in main
    result = function(*args, **kwargs)
File "errors.py", line 10, in broken_fetch
    raise RuntimeError
RuntimeError
Raising exception 
Traceback (most recent call last):
File "/usr/local/lib/python2.7/site-packages/eventlet/hubs/hub.py", line 336, in fire_timers
    timer()
File "/usr/local/lib/python2.7/site-packages/eventlet/hubs/timer.py", line 56, in __call__
    cb(*args, **kw)
File "/usr/local/lib/python2.7/site-packages/eventlet/greenthread.py", line 192, in main
    result = function(*args, **kwargs)
File "errors.py", line 10, in broken_fetch
    raise RuntimeError
RuntimeError
F
======================================================================
FAIL: test_error_is_bubbled_up (__main__.TestPool)
----------------------------------------------------------------------
Traceback (most recent call last):
File "errors.py", line 21, in test_error_is_bubbled_up
    pool.waitall()
AssertionError: RuntimeError not raised

----------------------------------------------------------------------
Ran 1 test in 0.003s

FAILED (failures=1)
4

1 に答える 1

1

Eventletのイベントループは、KeyboardInterruptおよびを除いて、すべての例外を飲み込みますSystemExitさまざまなイベントレットハブwait()の実装を確認してください。次の抜粋は、selectハブのwait()からのものです。

for listeners, events in ((readers, r), (writers, w)):
    for fileno in events:
        try:
            listeners.get(fileno, noop).cb(fileno)
        except self.SYSTEM_EXCEPTIONS:
            raise
        except:
            self.squelch_exception(fileno, sys.exc_info())
            clear_sys_exc_info()

これを回避するには、例外情報を値として渡し、後でメインスレッドで処理します。

import unittest2
import sys
import eventlet


def broken_fetch(url):
    print " Raising exception "
    try:
        raise RuntimeError
    except:
        return sys.exc_info()

class TestPool(unittest2.TestCase):

    def test_error_is_bubbled_up(self):
        with self.assertRaises(RuntimeError):
            pool = eventlet.GreenPool(100)
            urls = ['http://google.com/', 'http://example.com/']
            for exc_info in pool.imap(broken_fetch, urls):
                if exc_info is not None:
                    exc_class, value, tb = exc_info
                    raise exc_class, value, tb

if __name__ == '__main__':
    unittest2.main()

DEBUGイベントレットが飲み込まれた例外を出力しないように、イベントレットのフラグをオフにすることをお勧めします。メインスレッドで例外を処理したい場合は、重複したトレースバック印刷に混乱したくないでしょう。

import eventlet.debug
eventlet.debug.hub_exceptions(False)
于 2013-01-29T10:57:41.913 に答える