/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)?
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.
lib.Types
, it imports the lib
directory as a package, then lib/Types.py
as a submodule inside it, creating module objects lib
and lib.Types
in sys.modules
.Types
, it imports Types.py
as a standalone module, creating a module object Types
in sys.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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With