编写适用于Python 2.7和Python 3.x的代码的doctests和示例时,we typically use # doctest: +IGNORE_EXCEPTION_DETAIL
to paper over differences between Python 2.x and 3.x tracebacks。例如,这会照顾BarError
vs music.BarError
,但它会因OSError(errno.ENOENT, ...)
和IOError(errno.ENOENT, ...)
而分崩离析,因为,请参阅:
import errno
def testme():
"""
Test doctest vs ENOENT
>>> testme()
Traceback (most recent call last):
...
OSError: [Errno 2] so far so good
"""
raise OSError(errno.ENOENT, 'so far so good')
if __name__ == '__main__':
import doctest
doctest.testmod()
当使用python2.7运行时,一切都很好:
$ python2 test3.py -v
Trying:
testme()
Expecting:
Traceback (most recent call last):
...
OSError: [Errno 2] so far so good
ok
1 items had no tests:
__main__
1 items passed all tests:
1 tests in __main__.testme
1 tests in 2 items.
1 passed and 0 failed.
Test passed.
然而,当使用Python 3.x运行时:
$ python3 test3.py
**********************************************************************
File "test3.py", line 7, in __main__.testme
Failed example:
testme()
Expected:
Traceback (most recent call last):
...
OSError: [Errno 2] so far so good
Got:
Traceback (most recent call last):
File "/usr/local/lib/python3.6/doctest.py", line 1330, in __run
compileflags, 1), test.globs)
File "<doctest __main__.testme[0]>", line 1, in <module>
testme()
File "test3.py", line 12, in testme
raise OSError(errno.ENOENT, 'so far so good')
FileNotFoundError: [Errno 2] so far so good
**********************************************************************
1 items had failures:
1 of 1 in __main__.testme
***Test Failed*** 1 failures.
Python 3.6用OSError
替换FileNotFoundError
。
同样的事情发生在IOError
上。文件test4.py
已将OSError
替换为IOError
中的raise
和文档字符串。没有引用所有内容:
$ python2 test4.py
$ python3 test4.py
...
FileNotFoundError: [Errno 2] so far so good
***Test Failed*** 1 failures.
使用IGNORE_EXCEPTION_DETAIL
没有帮助,因为(显然)只会在错误消息中的第一个冒号之前跳过前缀.
,这里的问题是字符串文字{{1 }和OSError
vs IOError
。
我有一个基于装饰的解决方案,我将其作为答案包含在内,但是有更好的方法吗?
答案 0 :(得分:0)
我有一个基于装饰器的解决方案,这不是最漂亮的事情:
2
现在代码可以在python2(2.7)或python3(3.x)中运行。
装饰器可能有点聪明(例如,不将[Errno]
硬编码为{{1}}值),但它可以工作。
有更好的解决方法吗?