【问题标题】:ValueError: wrapper loop when unwrappingValueError:展开时的包装循环
【发布时间】:2018-03-14 07:07:43
【问题描述】:

Python3 测试用例(文档测试)在我的示例代码中失败。但在 Python2 中同样可以正常工作。

test.py

class Test(object):
    def __init__(self, a=0):
        self.a = a

    def __getattr__(self, attr):
        return Test(a=str(self.a) + attr)

tst.py

from test import Test

t = Test()

运行测试用例:python3 -m doctest -v tst.py

错误:

Traceback (most recent call last):
  File "/usr/lib/python3.6/runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "/usr/lib/python3.6/runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "/usr/lib/python3.6/doctest.py", line 2787, in <module>
    sys.exit(_test())
  File "/usr/lib/python3.6/doctest.py", line 2777, in _test
    failures, _ = testmod(m, verbose=verbose, optionflags=options)
  File "/usr/lib/python3.6/doctest.py", line 1950, in testmod
    for test in finder.find(m, name, globs=globs, extraglobs=extraglobs):
  File "/usr/lib/python3.6/doctest.py", line 933, in find
    self._find(tests, obj, name, module, source_lines, globs, {})
  File "/usr/lib/python3.6/doctest.py", line 992, in _find
    if ((inspect.isroutine(inspect.unwrap(val))
  File "/usr/lib/python3.6/inspect.py", line 513, in unwrap
    raise ValueError('wrapper loop when unwrapping {!r}'.format(f))
ValueError: wrapper loop when unwrapping <test.Test object at 0x7f6e80028550>

谁能帮忙解决这个错误。

谢谢。

【问题讨论】:

  • @Aran-Fey test.py 的代码已经在问题中了。
  • 没关系。我设法重现了它。

标签: python doctest


【解决方案1】:

这可以说是 doctest 中的一个错误。正在发生的事情是 doctest 正在搜索带有 docstring 的函数/方法/可调用对象,并且在这样做的同时它是 unwrapping 它找到的任何装饰器。为什么会这样,我不知道。但无论如何,doctest 最终会调用inspect.unwrap(t)(其中tTest 实例),这基本上相当于这样做:

while True:
   try:
       t = t.__wrapped__
   except AttributeError:
       break

因为tTest 实例,所以访问t.__wrapped__ 调用__getattr__ 并返回一个新的Test 实例。这将永远持续下去,但inspect.unwrap 足够聪明,可以注意到它没有到达任何地方,并抛出异常而不是进入无限循环。


作为一种解决方法,您可以重写 __getattr__ 方法以在访问 __wrapped__ 时抛出 AttributeError。更好的是,当访问 any dunder-attribute 时抛出 AttributeError:

def __getattr__(self, attr):
    if attr.startswith('__') and attr.endswith('__'):
        raise AttributeError
    return Test(a=str(self.a) + attr)

【讨论】:

  • 好吧,为这个干杯:) 这个错误现在以某种方式提交给doctest了吗? 2018 年还在这里。
  • @iago-lito 不知道。我既没有报告它,也没有搜索现有的错误报告。
  • 有一个错误:bugs.python.org/issue35753。它被标记为“阶段:已解决”,但仍然是“状态:打开”。
  • bugs.python.org/issue35753 已合并,将成为 python3.10 的一部分
【解决方案2】:

对于unittest.mock,尝试将项目导入为

from unittest import mock

而不是

from unittest.mock import patch

这对我来说解决了这个错误。

【讨论】:

  • 也为我工作。非常感谢!
猜你喜欢
  • 2021-10-04
  • 2010-09-16
  • 2016-10-27
  • 1970-01-01
  • 2016-08-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-23
相关资源
最近更新 更多