isinstance fails for a type imported via package and from the same module directly
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
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.