如何捕获gen.Task内部的异常?

我使用的是python 2.7,龙卷风4.5


以下代码不起作用: except 块不会被触发。我不明白为什么?


@gen.coroutine

def co_do_thing():

  yield gen.Task(do_thing)


def do_thing(callback):

  try:

    a, b = ...

    result = maybe_throw(a, b, callback)

  except Exception as e:

    # this block is not called

    if a:

      raise ApiError("called with A")

    elif b:

      raise ApiError("called with B")

    else:

      raise e


def maybe_throw(arg1, arg2, callback):

  if random.random() < 0.5:

    raise AssertionError("yikes")

  callback("done")

co_do_thing相反,我可以在调用周围捕获异常gen.Task;但后来我不知道我如何调用的上下文maybe_throw。maybe_throw就我而言,引发较低级别的异常并让调用者根据输入将其转换为人类可读的错误更有意义。


我是否只需要重构它以在较低级别调用 gen.Task ?那会很烦人:/


温温酱
浏览 90回答 1
1回答

暮色呼如

当我测试它似乎有效时,会引发异常。下面是简单的测试套件:import q&nbsp; # q.py is the file with question's codeimport unittestfrom mock import patch, Mockfrom tornado.testing import gen_test, AsyncTestCaseclass MyTest(AsyncTestCase):&nbsp; &nbsp; def setUp(self):&nbsp; &nbsp; &nbsp; &nbsp; self.mock_random = patch('q.random').start()&nbsp; &nbsp; &nbsp; &nbsp; AsyncTestCase.setUp(self)&nbsp; &nbsp; def tearDown(self):&nbsp; &nbsp; &nbsp; &nbsp; AsyncTestCase.tearDown(self)&nbsp; &nbsp; &nbsp; &nbsp; patch.stopall()&nbsp; &nbsp; @gen_test&nbsp; &nbsp; def test_no_error(self):&nbsp; &nbsp; &nbsp; &nbsp; self.mock_random.return_value = 0.7&nbsp; &nbsp; &nbsp; &nbsp; res = yield q.co_do_thing()&nbsp; &nbsp; &nbsp; &nbsp; self.assertEqual(res, 'done')&nbsp; &nbsp; @gen_test&nbsp; &nbsp; def test_exception(self):&nbsp; &nbsp; &nbsp; &nbsp; self.mock_random.return_value = 0.1&nbsp; &nbsp; &nbsp; &nbsp; with self.assertRaises(Exception) as ctx:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; yield q.co_do_thing()&nbsp; &nbsp; &nbsp; &nbsp; self.assertEqual(ctx.exception.message, 'called with A')if __name__ == '__main__':&nbsp; &nbsp; unittest.main()测试通过了:..----------------------------------------------------------------------Ran 2 tests in 0.002sOK这是q.py,我添加了 return 语句来测试它。from random import randomfrom tornado import gen@gen.coroutinedef co_do_thing():&nbsp; &nbsp; res = yield gen.Task(do_thing)&nbsp; &nbsp; # added: to enable to test it meaningfully&nbsp; &nbsp; raise gen.Return(res)def do_thing(callback):&nbsp; &nbsp; try:&nbsp; &nbsp; &nbsp; &nbsp; a, b = 22, 33&nbsp; &nbsp; &nbsp; &nbsp; result = maybe_throw(a, b, callback)&nbsp; &nbsp; except Exception as e:&nbsp; &nbsp; &nbsp; &nbsp; if a:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; raise Exception("called with A")&nbsp; &nbsp; &nbsp; &nbsp; elif b:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; raise Exception("called with B")&nbsp; &nbsp; &nbsp; &nbsp; else:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; raise edef maybe_throw(arg1, arg2, callback):&nbsp; &nbsp; if random() < 0.5:&nbsp; &nbsp; &nbsp; &nbsp; raise AssertionError("yikes")&nbsp; &nbsp; callback("done")
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python