python import机制
python的import语句
1 命名空间
在C语言中有作用域空间,python中有命名空间,表示在对应位置可以访问那些变量或者函数。python分为3个命名空间
-
built-in命名空间
- 内容:python中的内置对象,比如char、int这些类型,abs、min这些函数,和Exception的异常等。
- 范围:整个程序,任何位置都可以访问(任何模块,任何类,任何函数内)
- 生命周期:解释器启动开始创建,一直到解释器退出
-
global命名空间
- 内容:也叫做模块空间,即包含了模块内部的所以对象,包括类,函数,变量和导入的模块。
- 范围:整个程序,任何位置都可以访问
- 生命周期:模块导入开始创建,一直到解释器退出
- 查看:globals()函数可以查看global命名空间的成员
-
local命名空间
- 内容:类似于c中的局部作用域,即包含函数内部的变量和导入的模块。
- 范围:函数内部可以访问,函数外就访问不了了
- 生命周期:函数调用时创建,函数结束后释放
- 查看:locals()函数可以查看local命名空间的成员
2 模块和包
-
模块
- 定义:就是一个.py的文件
- 内容:完成一个小功能的python文件,包含类,函数,和变量
-
包
- 定义:就是一个包含__init__.py文件的文件夹
- 内容:包可以认为是完成一个大功能的集合体,包含多个模块,这些模块在__init__.py中进行导入管理。
- all:__all__是一个特殊变量,导入包的时候,会把__all__的成员导入到命名空间,不在的就不会被导入
在xlwings的init.py中,会将main、utils中的成员导入到__init__.py(即xlwings这个模块中)在其他程序中import xlwings as xw
导入xlwings,那么就把xlwings这个包导入了,且这个包中包含App、Book、sheets等成员。
xlwings/init.py
from .main import (App,Book,sheets...)
__all__ = ('App', 'Book', 'sheets', ...)
3 导入模块(包)和导入成员
每个模块都都有各自的命名空间(global命名空间),且命名空间是相互隔离的。如果模块A要访问模块B,有两种方法。
- 导入模块(包)
把B模块导入到A模块中(A模块的global空间和local空间都可以),让B模块成为A模块global空间或local空间中的一一个成员。
test.py
import xlwings # 把xlwings导入到test模块的global空间
def func():
import numpy #把numpy导入到了func的local空间
- 导入成员
把B模块的成员导入到A模块中(A模块的global空间和local空间都可以),让B模块的成员成为A模块global空间或local空间中的一一个成员。
test.py
from xlwings import App # 把xlwings.App成员导入到test模块的global空间
#import xlwings.App # 把xlwings.App成员导入到test模块的global空间
def func():
from optparse import OptionParser # 把optparse导入的func的local空间
- 多级导入
xlwings
|---- __init__.py
|---- main.py
|---- conversion
|---- __init__.py
|---- framework.py
|---- ext
|---- __init__.py
|---- sql.py
目录,对象都可以作为层级
from xlwings.converion import converter # 目录/包,导入包中的某个对象
from xlwings.App import api # 导入包中对象的某个成员,App Class中的api函数
4 导入顺序
python导入分为2步
-
查询sys.modules是否有需要导入的模块或者包
sys.modules相对于是一个模块的管理的cache,且解释器启动的时候会把built-in的包和模块添加到sys.modules这个字典中。后续执行import与的时候优先在这个字典中查找,每找到才去sys.path中搜索,且找到以后会把模块或者包添加到sys.modules这个字典中。 -
查找sys.path路径中是否有需要导入的模块或者包
sys.path是一个队列,保存了一些列路径,包括当前python文件的目录(sys.path[0])和一系列的包的存放路径,这个与python安装的有关系,通常会把python存放第三方包的几个路径都加入进去。
依次搜索,所以当前目录下优先级最高
['C:\\Users\\USER\\OneDrive\\文档\\pythonProject2',
'C:\\Users\\USER\\OneDrive\\文档\\pythonProject2',
'C:\\Program Files\\python3.9.12\\python39.zip',
'C:\\Program Files\\python3.9.12\\DLLs',
'C:\\Program Files\\python3.9.12\\lib',
'C:\\Program Files\\python3.9.12',
'C:\\Users\\USER\\AppData\\Roaming\\Python\\Python39\\site-packages',
'C:\\Users\\USER\\AppData\\Roaming\\Python\\Python39\\site-packages\\win32',
'C:\\Users\\USER\\AppData\\Roaming\\Python\\Python39\\site-packages\\win32\\lib',
'C:\\Users\\USER\\AppData\\Roaming\\Python\\Python39\\site-packages\\Pythonwin',
'C:\\Program Files\\python3.9.12\\lib\\site-packages']
5 添加搜索路径
如果要找的模块(.py文件)或者包(包含__init__.py的目录)不在当前目录下,且不在系统设置的搜索目录下,那么就需要在导入模块/包之前添加搜索路径。
# 这个语句要放在import语句之前才行
sys.path.append("/home/ydh/py/lib/") # lib目录为存放自己定义module的路径。
import genFile # 导入genFile.py模块
linux中通常缺少需要的包,又不想把包跟脚本文件放在一个目录下,可以在导入包之前修改sys.path,包存放包的目录添加进去。比如pycharm中的venv
sys.path.append(__path__ + '/venv/Lib/site-packages')
import xlwings
6 导入与执行
导入包和导入模块都会执行相应的文件
import package # 会执行package/__init__.py
import module # 会执行packge/module.py
- package:
构造名字为package_name的module对象,并把__all__中的成员名的对象加入到构造的module对象中
import xlwings as xw
,构造一个名字为xw的module对象,执行__init__.py把App,Book,sheets对象添加到这个module对象中 - module:
- 构造一个module_name的module对象,这个module中有什么对象就加什么对象。
- name:import执行的时候,__name__的值为"module_name",但是直接执行
python module.py
,那么__name__值为"main"