python import机制

python的import语句

1 命名空间

在C语言中有作用域空间,python中有命名空间,表示在对应位置可以访问那些变量或者函数。python分为3个命名空间

  1. built-in命名空间

    • 内容:python中的内置对象,比如char、int这些类型,abs、min这些函数,和Exception的异常等。
    • 范围:整个程序,任何位置都可以访问(任何模块,任何类,任何函数内)
    • 生命周期:解释器启动开始创建,一直到解释器退出
  2. global命名空间

    • 内容:也叫做模块空间,即包含了模块内部的所以对象,包括类,函数,变量和导入的模块
    • 范围:整个程序,任何位置都可以访问
    • 生命周期:模块导入开始创建,一直到解释器退出
    • 查看:globals()函数可以查看global命名空间的成员
  3. local命名空间

    • 内容:类似于c中的局部作用域,即包含函数内部的变量和导入的模块
    • 范围:函数内部可以访问,函数外就访问不了了
    • 生命周期:函数调用时创建,函数结束后释放
    • 查看:locals()函数可以查看local命名空间的成员

img

2 模块和包

  1. 模块

    • 定义:就是一个.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,有两种方法。

  1. 导入模块(包)

把B模块导入到A模块中(A模块的global空间和local空间都可以),让B模块成为A模块global空间或local空间中的一一个成员。

test.py

import xlwings      # 把xlwings导入到test模块的global空间
def func():
    import numpy    #把numpy导入到了func的local空间
  1. 导入成员

把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空间
  1. 多级导入
  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步

img

  1. 查询sys.modules是否有需要导入的模块或者包
    sys.modules相对于是一个模块的管理的cache,且解释器启动的时候会把built-in的包和模块添加到sys.modules这个字典中。后续执行import与的时候优先在这个字典中查找,每找到才去sys.path中搜索,且找到以后会把模块或者包添加到sys.modules这个字典中。

  2. 查找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"

7

posted @ 2023-09-11 10:44  下夕阳  阅读(19)  评论(0编辑  收藏  举报