前言
在Python中,一个.py文件代表一个Module。在Module中可以是任何的符合Python文件格式的Python脚本。了解Module导入机制大有用处。
1. Module组成
一个.py文件就是一个module。Module中包括attribute, function等。 这里说的attribute其实是module的global variable。
我们创建1个test1.py文件,代码如下
# 定义1个全局变量a
a = 1
# 声明一个全局变量moduleName
global moduleName
# 定义一个函数printModuleName
def printModuleName():
print(a + 2)
print(__name__)
print(moduleName)
print(dir())
这里我们定义了3个全局变量a
、moduleName
、printModuleName
,除了我们自己定义的以外还有module内置的全局变量
1.1 Module 内置全局变量
上面我们说到了,每一个模块都有内置的全局变量,我们可以使用dir()
函数,用于查看模块内容,例如上面的例子中,使用dir()
查看结果如下:
['__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'a', 'moduleName', 'printModuleName']
其中a, moduleName, printModuleName 是由用户自定义的。其他的全是内置的。下面介绍几个常用的内置全局变量
1.1.1 __name__
指的是当前模块的名称,比如上面的test1.py
,模块的名称默认就是test1,如果一个module是程序的入口,那么__name__=__'main'__
,这也是我们经常看到用到的
1.1.2 __builtins__
它就是内置模块builtins
的引用。可以通过如下代码测试:
import builtins
print(builtins == __builtins__)
打印结果为True
,在Python代码里,不需要我们导入就能直接使用的函数、类等,都是在这个内置模块里的。例如:range
、dir
1.1.3 __doc__
它就是module的文档说明,具体是文件头之后、代码(包含import)之前的第一个多行注释
,测试如下
点击查看代码
"""
模块导入机制测试
"""
import builtins
# 定义1个全局变量a
a = 1
# 声明一个全局变量moduleName
global moduleName
# 定义一个函数printModuleName
def printModuleName():
print(a + 2)
print(__name__)
print(moduleName)
print(__doc__)
最后打印结果为
模块导入机制测试
当然如果你想查看某个方法的说明,也可以这么使用
1.1.4 __file__
当前module所在的文件的绝对路径
1.1.5 __package__
当前module所在的包名。如果没有,为None。
2. 包package
??为避免模块名冲突,Python引入了按目录组织模块的方法,称之为包(package)。包是含有Python模块的文件夹。
??当一个文件夹下有init.py
时,意为该文件夹是一个包(package),其下的多个模块(module)构成一个整体,而这些模块(module)都可通过同一个包(package)导入其他代码中。
??其中init.py
文件用于组织包(package),方便管理各个模块之间的引用、控制着包的导入行为。
??该文件可以什么内容都不写,即为空文件,存在即可,相当于一个标记。
??但若想使用from pacakge_1 import *
这种形式的写法,需在init.py
中加上:__all__ = ['file_a', 'file_b']
,并且package_1下有file_a.py
和file_b.py
,在导入时init.py
文件将被执行。
??但不建议在init.py
中写模块,以保证该文件简单。不过可在init.py
导入我们需要的模块,以便避免一个个导入、方便使用。
??其中,__all__
是一个重要的变量,用来指定此包(package)被import *时,哪些模块(module)会被import进【当前作用域中】。不在__all__
列表中的模块不会被其他程序引用。可以重写__all__
,如__all__
= ['当前所属包模块1名字', '模块1名字']
,如果写了这个,则会按列表中的模块名进行导入
??在模糊导入时,形如from package import *
,*是由__all__
定义的。
??当我们在导入一个包(package)时(会先加载__init__.py
定义的引入模块,然后再运行其他代码),实际上是导入的它的__init__.py
文件(导入时,该文件自动运行,助我们一下导入该包中的多个模块)。我们可以在 init.py中再导入其他的包(package)或模块或自定义类。
2.1 实战案例
首先我们创建3个包,分别是test
、test2
、test3
test包下创建test1.py
用来执行测试
test2包下创建file_a.py
、file_b.py
,用来测试包的导入
test3包下创建file_c.py
,辅助测试
具体结构如下:
核心代码在test2/__init__.py
中如下
__all__ = ['file_a', 'file_b', 'file_c', 'test_d']
from test3 import file_c
def test_d():
return "test_d"
解释下,当我们在test/test1.py
中写了from test2 import *
这句代码,程序不是直接导入test2下的所有模块,而是导入__init__.py
文件并自动运行,由于我们写了__all__ = ['file_a', 'file_b', 'file_c', 'test_d']
,file_a和file_b是当下包中的模块,file_c是我们从test3包中导入的,test_d是__init__.py
下我们定义的函数。
所以from test2 import *
就是把__all__
中指定的模块和函数导入进来了,接着我们查看test1.py
下的代码
from test2 import *
print(file_a.a())
print(file_b.b())
print(file_c.c())
print(test_d())
如果打印有结果,则证明了导入成功,并且导入的是__all__
下的模块和函数
3.sys.modules、命名空间
3.1 sys.modules
s