我观察到Python 3 unittest的奇怪行为。在函数testValue
中测试用例测试不存在的模块。
import sys
import unittest
class ModuleTest(unittest.TestCase):
def testValue(self):
import unknown_module
result = unknown_module.value
self.assertEqual(0.0, result)
if __name__ == "__main__":
print(sys.version)
unittest.main()
Python2正确地给出了以下输出:
2.7.5 (default, May 15 2013, 22:44:16) [MSC v.1500 64 bit (AMD64)]
E
======================================================================
ERROR: testValue (__main__.ModuleTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "C:\bin\WinPython-64bit-2.7.5.1\workspace\unknown_module_test.py", line 7, in testValue
import unknown_module
ImportError: No module named unknown_module
----------------------------------------------------------------------
Ran 1 test in 0.000s
FAILED (errors=1)
但是当引用unknown_module.value
时,Python 3声称存在AttributeError。
3.3.0 (v3.3.0:bd8afb90ebf2, Sep 29 2012, 10:55:48) [MSC v.1600 32 bit (Intel)]
E
======================================================================
ERROR: testValue (__main__.ModuleTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "unknown_module_test.py", line 8, in testValue
result = unknown_module.value
AttributeError: 'module' object has no attribute 'value'
----------------------------------------------------------------------
Ran 1 test in 0.016s
FAILED (errors=1)
为什么不像Python 2那样抛出Python 3 ImportError
?
答案 0 :(得分:3)
您正在导入隐式命名空间包。引自Python 3.3 What's New page:
对不需要__init__.py标记文件的包目录的本机支持,并且可以自动跨越多个路径段(受各种第三方方法命名空间包的启发,如PEP 420中所述)
和PEP 420 Implicit Namespace Packages:
如果扫描完成而未返回模块或包,并且至少记录了一个目录,则会创建命名空间包。新的命名空间包:
- 将
__path__
属性设置为扫描期间找到并记录的可迭代路径字符串。- 没有
__file__
属性。
和
命名空间包和常规包非常相似。不同之处是:
- 命名空间包的部分不一定都来自相同的目录结构,甚至来自同一个加载器。常规包是自包含的:所有部分都存在于同一目录层次结构中。
- 命名空间包没有
__file__
属性。- 命名空间包'
__path__
属性是字符串的只读可迭代,在修改父路径时会自动更新。- 命名空间包没有
__init__.py
模块。- 命名空间包为
__loader__
属性提供了不同类型的对象。
从unknown_module
中删除sys.path
目录,您的测试将会像在早期Python版本中那样失败。