【发布时间】:2014-08-05 05:18:08
【问题描述】:
我很难让我的测试框架同时适用于 Python2 和 Python3 的 C 扩展模块。我喜欢通过doctest 运行我的文档字符串,以确保我不会向我的用户提供错误信息,所以我想运行doctest 作为我测试的一部分。
我不认为我的问题的根源是文档字符串本身,而是doctest 模块如何尝试读取我的扩展模块。如果我使用 Python2 运行 doctest(在针对 Python2 编译的模块上),我会得到我期望的输出:
$ python -m doctest myext.so -v
...
1 items passed all tests:
98 tests in myext.so
98 tests in 1 items.
98 passed and 0 failed.
Test passed.
然而,当我用 Python3 做同样的事情时,我得到一个UnicodeDecodeError:
$ python3 -m doctest myext3.so -v
Traceback (most recent call last):
...
File "/usr/local/Cellar/python3/3.3.3/Frameworks/Python.framework/Versions/3.3/lib/python3.3/doctest.py", line 223, in _load_testfile
return f.read(), filename
File "/usr/local/Cellar/python3/3.3.3/Frameworks/Python.framework/Versions/3.3/lib/python3.3/codecs.py", line 301, in decode
(result, consumed) = self._buffer_decode(data, self.errors, final)
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xcf in position 0: invalid continuation byte
为了获得更多信息,我通过pytest 运行了它并带有完整的回溯:
$ python3 -m pytest --doctest-glob "*.so" --full-trace
...
self = <encodings.utf_8.IncrementalDecoder object at 0x102ff5110>
input = b'\xcf\xfa\xed\xfe\x07\x00\x00\x01\x03\x00\x00\x00\x08\x00\x00\x00\r\x00\x00\x00\xd0\x05\x00\x00\x85\x00\x00\x00\x00\x...edString\x00_PyUnicode_FromString\x00_Py_BuildValue\x00__Py_FalseStruct\x00__Py_TrueStruct\x00dyld_stub_binder\x00\x00'
final = True
def decode(self, input, final=False):
# decode input (taking the buffer into account)
data = self.buffer + input
> (result, consumed) = self._buffer_decode(data, self.errors, final)
E UnicodeDecodeError: 'utf-8' codec can't decode byte 0xcf in position 0: invalid continuation byte
/usr/local/Cellar/python3/3.3.3/Frameworks/Python.framework/Versions/3.3/lib/python3.3/codecs.py:301: UnicodeDecodeError
看起来doctest 实际上是读取 .so 文件以获取文档字符串(而不是导入模块),但 Python3 不知道如何解码输入。我可以通过自己尝试读取.so 文件来复制字节字符串和回溯来确认这一点:
$ python3
Python 3.3.3 (default, Dec 10 2013, 20:13:18)
[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.2.79)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> open('myext3.so').read()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/Cellar/python3/3.3.3/Frameworks/Python.framework/Versions/3.3/lib/python3.3/codecs.py", line 301, in decode
(result, consumed) = self._buffer_decode(data, self.errors, final)
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xcf in position 0: invalid continuation byte
>>> open('myext3.so', 'rb').read()
b'\xcf\xfa\xed\xfe\x07\x00\x00\x01\x03\x00\x00\x00\x08\x00\x00\x00\r\x00\x00\x00\xd0\x05...'
以前有没有其他人遇到过这个问题?有没有一种标准(或不那么标准)的方法可以让doctest 在 python3 上对 C 扩展模块执行测试?
更新:我还应该补充一点,我在 Travis-CI (see here) 上得到了相同的结果,所以它并不特定于我的本地构建。
【问题讨论】:
-
也许您需要为 Python 3 编译不同版本的
doctest? -
对于 python3,我正在使用来自 std 库的 doctest 模块。有没有其他推荐的版本? doctest不是纯python模块吗,还需要编译吗?
-
对不起,我以前从未使用过
doctest,没有意识到它是一个内置模块。也许您的 PYTHONPATH 将第 2 版模块放在第 3 版之前? -
我的 PYTHONPATH 是空的...我完全依赖
sys.path中的硬编码路径。此外,在第一个回溯中,您可以看到doctest.py文件位于 python 3.3 标准库位置,所以我认为这不是问题所在。感谢您的建议,请继续提供!
标签: python python-3.x doctest python-c-extension