Python中Package导入机制与模块访问详解
本文深入解析Python中Package的导入机制,区分Regular Package与Namespace Package。重点讲解__init__.py的作用、pkg.__path__与pkg.__file__属性的区别,以及import pkg与import pkg.mod1在sys.modules缓存和全局变量中的行为差异,帮助开发者正确访问子模块。
Python Package与Module的基本概念
在Python中,Package是组织代码的有效方式。Module通常对应单个文件,可通过import语句导入;而Package则对应一个目录结构。接下来我们将探讨多层嵌套目录下的导入方式。
>>> import collections,socket
>>> print(collections.__path__)
['/anaconda3/envs/py38/lib/python3.8/collections']
>>> print(socket.__path__)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: module 'socket' has no attribute '__path__'
以Python标准库为例,collections是一个Package(目录结构),而socket是一个Module(单个文件)。两者的关键区别在于Package具有__path__属性,可通过__path__访问存放Python文件的目录路径,而普通Module不具备此属性。
Python Package的两种类型
Python中主要存在两种Package类型:Regular Package(常规包)和Namespace Package(命名空间包)。
Regular Package是最常见的包形式。
Regular Package结构与__init__.py作用
首先分析Regular Package的结构。
main.py
pkg1
---__init__.py
在项目目录下创建文件夹pkg1,并在其中放置文件__init__.py,该目录即构成Regular Package。包名即为文件夹名,可直接导入。在__init__.py文件中添加如下代码。
print("importing pk1")
def hi_say():
print("pkg1 say hi")
在main.py中执行import pkg1语句。Python通过Finder定位Package位置,PathFinder在sys.path中搜索。由于sys.path首个路径为当前目录,Python能定位到pkg1。导入Package时,会自动执行其下的__init__.py文件。导入后生成的编译代码对象,可通过pkg1.hi_say()调用。
print(pkg1.__path__)
利用pkg1的__path__属性,可获取pkg1目录的绝对路径。
print(pkg1.__file__)
通过__file__属性,可得到__init__.py文件的绝对路径。
print(pkg1.__package__)
此外,可通过Package的__package__属性获取Package名称,或通过__name__获取Module名称。
Package下子Module的导入与访问机制
进一步增加复杂度,在pkg1文件夹下新建mod1.py文件。
main.py
pkg1
---__init__.py
---mod1.py
__init__.py文件内容如下。
print("importing pk1")
在mod1.py中输出“import mod1”信息,并定义say_hi函数。目标是导入该Module并执行其中的say_hi方法。
print("importing mod1")
def say_hi():
print("pkg1 say hi")
import sys
import pkg1
print('pkg1' in globals())#True
print('pkg1' in sys.modules)#True
执行import pkg1时,会创建指向Module对象的引用并加入全局变量,同时该Module会被添加到sys.modules缓存中。
若直接通过pkg1.mod1访问mod1 Module,将抛出错误,提示该属性不存在。
AttributeError: module 'pkg1' has no attribute 'mod1'
这表明仅导入Package并不会自动导入其下的子Module,因此会出现上述错误。要正确导入pkg1下的mod1,需使用import pkg1.mod1这种标准方式。
import sys
import pkg1.mod1
请注意,正确导入mod1的方式是import pkg1.mod1。从输出结果可见,Python先执行__init__.py,即先导入Package pkg1,随后再导入Module mod1,遵循此顺序。
importing pk1
importing mod1
采用上述方式即可访问Module mod1中的say_hi()方法。
pkg1.mod1.say_hi()
print('pkg1' in sys.modules)#True
print('pkg1.mod1' in sys.modules)#True
print('pkg1' in globals())#True
print('pkg1.mod1' in globals())#False
观察输出可知,pkg1和pkg1.mod1均存在于sys.modules缓存中。但仅pkg1位于全局变量中,必须通过pkg1的属性来访问mod1。
简要总结:要访问Package下的Module,首先访问Package会执行其下的__init__.py文件,随后执行Module代码。sys.modules中保存pkg1和pkg1.mod1分别指向两个Module对象的内存地址。
至此,关于如何在Python中导入Package的文章介绍完毕。更多相关内容请搜索本站历史文章或继续浏览后续文章,感谢支持!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













