对于通过包和直接从同一模块导入的类型,isinstance失败
/Project
|-- main.py
|--/lib
| |--__init__.py
| |--foo.py
| |--Types.py
/Project/lib
已添加到PYTHONPATH
变量中。
Types.py:
class Custom(object):
def __init__(self):
a = 1
b = 2
foo.py:
from Types import Custom
def foo(o):
assert isinstance(o, Custom)
最后,来自 main.py :
from lib.Types import Custom
from lib.foo import foo
a = Custom()
foo(a)
现在的问题是,它a
的类型为lib.foo.Custom
,而isinstance调用将检查其是否等于foo.Custom
,这显然返回false。
如何避免此问题,而不必更改库(lib)中的任何内容?
-
您不应该同时制作
lib
一个程序包并将其添加到中PYTHONPATH
。这样就可以lib.
直接或直接导入其模块,从而为失败做好准备。如你看到的,
lib.Types.Custom != Types.Custom
Python搜索导入路径并解析其找到的适当条目。
- 导入时
lib.Types
,它将lib
目录导入为一个包,然后导入lib/Types.py
为其中的子模块,lib
并lib.Types
在中创建模块对象sys.modules
。 - 当您导入
Types
,它导入Types.py
作为一个独立的模块,创建模块对象Types
在sys.modules
。
所以,
Types
和lib.Types
最终成为两个不同的模块对象。Python不会检查它们是否是同一文件,以使事情变得简单并避免再次猜测。(这实际上在Python的Import System中的Unwary陷阱中列为“双重导入陷阱”。)
如果
lib
从中删除PYTHONPATH
,则导入lib/foo.py
将需要成为相对导入:from .Types import Custom
或绝对导入:
from lib.Types import Custom
- 导入时