ValueError:解包时的包装循环

Ram*_*ati 6 python doctest

Python3测试用例(doctests)失败了我的示例代码.但同样在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)
Run Code Online (Sandbox Code Playgroud)

tst.py

from test import Test

t = Test()
Run Code Online (Sandbox Code Playgroud)

运行测试用例: 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>
Run Code Online (Sandbox Code Playgroud)

任何人都可以帮助我们如何克服这个错误.

谢谢.

Ara*_*Fey 6

这可以说是 doctest 中的一个错误。什么情况是,文档测试正在搜索与文档字符串函数/方法/可调用,虽然这样做它的展开发现任何装饰。为什么会这样,我不知道。但无论如何, doctest 最终会调用inspect.unwrap(t)( wheret是一个Test实例),这本质上等同于这样做:

while True:
   try:
       t = t.__wrapped__
   except AttributeError:
       break
Run Code Online (Sandbox Code Playgroud)

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


作为一种解决方法,您可以重写您的__getattr__方法以抛出AttributeError何时__wrapped__被访问。更好的是,当访问任何dunder属性时抛出 AttributeError :

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


All*_*son 6

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

from unittest import mock
Run Code Online (Sandbox Code Playgroud)

代替

from unittest.mock import patch
Run Code Online (Sandbox Code Playgroud)

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