1.问题重现
最近开发时需要将一个别人的python项目作为submodule引入,调用的时候遇到了奇怪的问题,最后定位到问题是import导致的。首先对问题做一个说明。
项目结构如下:
Project/
main.py
submodule/
__init__.py
handler.py
tools.py
导致问题的代码部分(对代码进行了简化)如下:
- main.py
import sys
import os
sys.path.append(os.path.dirname(os.path.realpath(__file__)) + "/submodule")
from submodule.handler import Handler
from submodule.tools import check
if __name__ == "__main__":
handler = Handler()
print("check result:{}".format(check(handler)))
- handler.py
class Handler:
pass
- tools.py
import sys
import os
from handler import Handler
def check(data):
return type(data) == type(Handler())
执行main.py后,输出的结果是:check result:False
,而我期望的结果是True
2.问题分析
很明显,上述结果说明传递进去的data
和Handler()
生成的实例类别不同,但这看起来很不合理:我明明import的是同一个类,为什么实例化之后判断类别会不同呢。将两个实例的类别打印出来发现:
type of data:<class 'submodule.handler.Handler'>
type of Handler():<class 'handler.Handler'>
可以看到两个实例的类别并不一样,并且很容易就可以发现,两个实例类比中Handler
的前缀刚好就是两个文件中import时候的路径,因此大概率是这个问题导致的(实际上也确实是)。
3.原理
3.1 python的import机制及module
导致这个问题的核心原因,在于python的import机制。当我们import一个module时,导入的并不是某个类的定义或者一段代码,而是一个实例化了一个module类:
>>> import submodule.handler as handler
>>> type(handler)
<class 'module'>
而所有的module,都被维护在一个大的字典sys.modules
中:
>>> import sys
>>> print(sys.modules)
{
'sys': <module 'sys' (built-in)>,
'builtins': <module 'builtins' (built-in)>,
'_frozen_importlib': <module '_frozen_importlib' (frozen)>,
......
}
其中的key就是我们import时候的名称或者说路径。在main.py
中打印sys.modules
,可以看到:
'submodule.handler': <module 'submodule.handler' from '/home/aabb/import_test/submodule/handler.py'>,
'handler': <module 'handler' from '/home/aabb/import_test/submodule/handler.py'>
尽管import“指向”了同一个文件,但实际上是两个不同的module,这两个module中的Handler
类也并不是同一个类(准确来说是对象。python中,类本身也是一个对象,可以参考python中类对象),因此其实例化的对象类型肯定不会相同。
3.2 解决方案
知道了上述原理,解决方案也就有了,那就是在项目内要统一import的路径。比较合理的方式是无论在项目内部还是项目外部,都从项目的根目录开始引用。我这个项目中的问题实际上是submodule中没有从根目录开始引用(不过人家这个项目本来也不是让别人拿来当submodule用的)
4. 后记
菜鸡的第一篇博客,问题也是个很简单的问题,不过我觉得是个很容易被忽略的问题(也可能是我太菜了_(:з)∠)_)。很早前就一直有想写博客的想法,但一直没有迈出第一步,这次也算开了个头。
如果有哪些地方写的有问题还请大佬们指正_(:з)∠)_
标签:submodule,python,handler,py,module,Handler,import From: https://www.cnblogs.com/qiangliang/p/17841599.html