问题
/Project
|-- main.py
|--/lib
| |--__init__.py
| |--foo.py
| |--Types.py
/Project/lib
has been added to the PYTHONPATH
variables.
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)
Finally, from main.py:
from lib.Types import Custom
from lib.foo import foo
a = Custom()
foo(a)
The problem now is, that a
is of type lib.foo.Custom
, while the isinstance call will check if it equals foo.Custom
, which obviously returns false.
How can I avoid this problem, without having to change anything in the library (lib)?
回答1:
You should not both make lib
a package and add it to PYTHONPATH
. This makes it possible to import its modules both as lib.
and directly, setting yourself up for failure.
As you can see,
lib.Types.Custom != Types.Custom
because of the way Python imports work.
Python searches the import path and parses an appropriate entry that it finds.
- When you import
lib.Types
, it imports thelib
directory as a package, thenlib/Types.py
as a submodule inside it, creating module objectslib
andlib.Types
insys.modules
. - When you import
Types
, it importsTypes.py
as a standalone module, creating a module objectTypes
insys.modules
.
So, Types
and lib.Types
end up as two different module objects. Python doesn't check if they are the same file to keep things simple and to avoid second-guessing you.
(This is actually listed in the Traps for the Unwary in Python’s Import System article as the "double import trap".)
If you remove lib
from PYTHONPATH
, the import in lib/foo.py
would need to become a relative import:
from .Types import Custom
or an absolute import:
from lib.Types import Custom
回答2:
When a module is imported thru two different path in the same process - like here with import Types
in foo.py
and import lib.Types
in main.py
, it is really imported twice, yielding two distinct module objects, each with it's own distinct functions and class instances (you can check by yourself using id(obj_or_class)
), effectively breaking is
and isinstance
tests.
The solution here would be to add Project
(not Project/lib
) to your pythonpath (fwiw that's what should have been done anyway - pythonpath/sys.path should be a list of directories containing packages and modules, not the packages directories themselves) and use from lib.Type import Custom
everywhere, so you only have one single instance of the module.
来源:https://stackoverflow.com/questions/46708659/isinstance-fails-for-a-type-imported-via-package-and-from-the-same-module-direct