我有一段动态创建异常
的代码。以这种方式创建的每个异常类都会覆盖其 __name__
:
def exception_injector(name, parent, module_dict):
class product_exception(parent):
pass
product_exception.__name__ = name
product_exception.__module__ = module_dict["__name__"]
module_dict[name] = product_exception
当我经常使用它时,它可以很好地打印所有内容:
>>> namespace = {"__name__": "some.module"}
>>> exception_injector("TestError", Exception, namespace)
>>> raise namespace["TestError"]("What's going on?")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
some.module.TestError: What's going on?
但是当我使用 unittest
模块时,会打印原始的 __name__
:
>>> import unittest
>>> class DemoTestCase(unittest.TestCase):
... def test_raise(self):
... namespace = {"__name__": "some.module"}
... exception_injector("TestError", Exception, namespace)
... namespace["TestError"]("What's going on?")
...
>>> unittest.main(defaultTest="DemoTestCase", argv=["demo"], exit=False)
E
======================================================================
ERROR: test_raise (__main__.DemoTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "<stdin>", line 3, in test_raise
some.module.exception_injector.<locals>.product_exception: What's going on?
----------------------------------------------------------------------
Ran 1 test in 0.000s
FAILED (errors=1)
<unittest.main.TestProgram object at 0x1017c3eb8>
unittest
模块可以从异常对象的何处获取原始信息?
最佳答案
单元测试使用 traceback
module格式化异常。您可以通过执行相同的操作来重现输出:
>>> import traceback
>>> try:
... raise namespace["TestError"]("What's going on?")
... except Exception as e:
... tb = traceback.TracebackException.from_exception(e)
... print(*tb.format())
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
some.module.exception_injector.<locals>.product_exception: What's going on?
正在打印的是对象__module__
属性值*,其中object.__qualname__
attribute附加(带有点分隔符),而不是 __module__
加 __name__
:
>>> namespace["TestError"].__qualname__
'exception_injector.<locals>.product_exception'
限定名称包括 full scope where the class was created (此处为函数名称,但这也可以包括类名称)。
如果您的目标是向模块的全局命名空间添加异常,则只需将其设置为与 name
相同的值即可:
>>> namespace["TestError"].__qualname__ = "TestError"
>>> try:
... raise namespace["TestError"]("What's going on?")
... except Exception as e:
... tb = traceback.TracebackException.from_exception(e)
... print(*tb.format())
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
some.module.TestError: What's going on?
或者在您的代码上下文中:
def exception_injector(name, parent, module_dict):
class product_exception(parent, details=args):
pass
product_exception.__name__ = name
product_exception.__qualname__ = name
product_exception.__module__ = module_dict["__name__"]
module_dict[name] = product_exception
* 如果模块名称是 __main__
或 builtins
,则回溯模块将忽略异常模块。
关于python - 运行 `python -m unittest` 会更改在回溯中打印覆盖 `__name__` 的异常的方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63871136/