Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
713 views
in Technique[技术] by (71.8m points)

python - isinstance fails for a type imported via package and from the same module directly

/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)?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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 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.
  • When you import 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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...