python中import原理
0. 前言
在 python 中引入 Module 是再常见不过了,那么当我们 import 时它做了什么事情呢?它是如何加载 Module 使用的呢?
1. 什么是 module?
一般,Module 是一个后缀为 .py 的文件,其 module 名称一般是文件名称去除 .py ,我们可以通过 __name__ 来查看 module 名称。
demo.py 是需要被引入的 module,main.py 是入口程序,它们在同一级目录。
# demo.py
print(__name__)# main.py
import demo>>> python main.py
demo
如果 module 为入口文件,则__name__为 __main__,这也是常见 if __name__ == __main__: 的写法由来。
# demo.py
print(__name__)>>> python demo.py
__main__
2. 什么是 Package?
包含了 __init__ 文件的目录为 Package,该目录包含多个 py 文件,都属于 Module。我们在 import package 时,会初始化执行 package 的 __init__.py 文件,然后将其作为一个 Module 对象给放在当前的全局变量中。
├───demo
│ │ __init__.py
| main.py
# __init__.py
print("demo __init__")# main.py
import demo
print(demo)
print(globals()["demo"])>>> python main.py
output:
demo __init__.py
<module 'demo' from 'D:\\code\\my_demo\\demo\\__init__.py'>
<module 'demo' from 'D:\\code\\my_demo\\demo\\__init__.py'>
可以看到 package 的名称 demo 是在 globals()中的,并且其是一个 module 对象,包含了该 __init__.py 文件所在的路径。
如果想要导入 package 下的 module,可以通过 from package import module 的方式将其加载到当前的全局变量中。
├───demo
│ │ __init__.py
| | a.py
| main.py
# __init__.py# a.py
class Demo:pass# main.py
from demo import a
print(a)
print(a.Demo)
print(globals()["a"])>>> python main.py
<module 'demo.a' from 'D:\\code\\my_demo\\demo\\a.py'>
<class 'demo.a.Demo'>
<module 'demo.a' from 'D:\\code\\my_demo\\demo\\a.py'>
3. module 缓存
- module 缓存初始化
在 python 程序初始化时,会将大批的内置 module 提前加载到内存中,保存在 sys.modules 中,这是一个字典,是以 module 名称或者 package 名称为 key,module 对象为 value 存储。
>>> import sys
>>> sys.modules
{... 'os': <module 'os' from '/usr/lib64/python3.6/os.py'> ...}
>>> sys.modules["os"].cpu_count()
8
>>> os.cpu_count()
Traceback (most recent call last):File "<stdin>", line 1, in <module>
NameError: name 'os' is not defined
- 将 module 添加到当前去全局变量中
既然提前加载了,但是这里为什么找不到 os 呢?这是因为虽然 sys.modules 中已经存在了,但是并没有把 os 加入到当前的全局变量中。
>>> globals()["os"]
Traceback (most recent call last):File "<stdin>", line 1, in <module>
KeyError: 'os'
所以当我们通过 import os 时,它会通过模块名称在 sys.modules 找到其 module 对象,然后再将其加入到当前的全局变量中,这样就可以使用它了。
>>> import os
>>> globals()["os"]
<module 'os' from '/usr/lib64/python3.6/os.py'>
>>> os.cpu_count()
8
>>> id(sys.modules["os"])
140260375998856
>>> id(os)
140260375998856
可以看到从 sys.modules 中拿到的 os 对象的地址和当前导入的 os 的地址是一致的,无论 import 多少次相同的 module,都是从该全局 sys.modules 中获取,拿到的都是同一个对象,也是单例模式实现的一种。
- 导入 module 中的属性
如果我只是引入 module 中的一个属性变量呢?那 sys.modules 中还是会加载该 module,将其属性变量作为全局变量引入。
>>> import sys
>>> sys.modules["json"]
Traceback (most recent call last):File "<stdin>", line 1, in <module>
KeyError: 'json'
>>> from json import load
>>> sys.modules["json"]
<module 'json' from '/usr/lib64/python3.6/json/__init__.py'>
- 模块不需要了,del 销毁
del 销毁的只是销毁当前全局变量中的变量,并不会影响 sys.modules 中的缓存。为什么不销毁 sys.modules 中的呢?是因为该销毁的 module 可能还会在其他的文件中引用。
>>> import json
>>> import sys
>>> sys.modules["json"]
<module 'json' from '/usr/lib64/python3.6/json/__init__.py'>
>>> globals()["json"]
<module 'json' from '/usr/lib64/python3.6/json/__init__.py'>
>>> del json
>>> sys.modules["json"]
<module 'json' from '/usr/lib64/python3.6/json/__init__.py'>
>>> globals()["json"]
Traceback (most recent call last):File "<stdin>", line 1, in <module>
KeyError: 'json'
- module 重新加载
因为每次 import 都是从 sys.modules 的缓存中获取,那么如果 module 文件变动,则无法拿到最新的 module,这个时候需要通过手动调用 importlib.reload 来重新加载,从本地文件中重新加载 module 对象到 sys.modules 中。
在当前目录下创建 demo.py 文件,内容为空
# demo.py>>> import demo
>>> demo.Demo
Traceback (most recent call last):File "<stdin>", line 1, in <module>
AttributeError: module 'demo' has no attribute 'Demo'
这个时候在 demo.py 中添加:
class Demo:pass
reload demo 后,可以看到加载到 Demo 了。
>>> reload(demo)
<module 'demo' from '/root/work/mydemo/demo.py'>
>>> demo.Demo
<class 'demo.Demo'>
那如果 import 的 module 或者 package 没有在 sys.modules 中呢,这个时候就要去 sys.path 中去本地搜索了。
4. 搜索路径
sys.path 是一个列表,其中包含了要去搜索 module 的本地路径。当 sys.modules 中查找不到 module 时,将会从该路径中搜索到 module 文件并将其加载到 sys.modules 中来。
sys.path 的路径的来源有:
- 运行脚本所在的目录
PYTHONPATH环境变量- python 安装时的默认设置
当在搜索路径找到该 module 的本地路径后,会将其加载到 sys.modules 中,然后再将其添加到当前的全局变量中。
5. 总结
import 的加载过程:
- 先从 sys.modules 中查看是否有导入的模块,有,则获取该模块,并加入到当前的全局变量中。
- 如果 sys.modules 中没有需要导入的模块,则按照 sys.path 中的目录路径进行搜索找到对应的模块文件再加载到 module 对象中返回。
相关文章:
python中import原理
0. 前言 在 python 中引入 Module 是再常见不过了,那么当我们 import 时它做了什么事情呢?它是如何加载 Module 使用的呢? 1. 什么是 module? 一般,Module 是一个后缀为 .py 的文件,其 module 名称一般…...
《Qt6开发及实例》6-4 显示SVG格式图片
目录 一、简介与设计 1.1 简介 1.2 设计 二、SvgWidget 2.1 鼠标滚轮事件 三、svgwindow 四、MainWindow 一、简介与设计 1.1 简介 1、SVG 的英文全称是 Scalable Vector Graphics,即可缩放的矢量图形。它是由万维网联盟(W3C)在 200…...
OpenGL ES 绘制一张图片
GLSL 语法与内建函数 GLSL 的修饰符与数据类型 GLSL 中变量的修饰符 const:修饰不可被外界改变的常量attribute:修饰经常更改的变量,只可以在顶点着色器中使用uniform:修饰不经常更改的变量,可用于顶点着色器和片段…...
Python 之 Pandas DataFrame 数据类型的行操作和常用属性和方法汇总
文章目录一、DataFrame 行操作1. 标签选取2. 数值型索引和切片3. 切片操作多行选取4. 添加数据行4.1 追加字典4.2 追加列表5. 删除数据行二、常用属性和方法汇总1. 转置2. axes3. dtypes4. empty5. columns6. shape7. values8. head() & tail()9. 修改列名 rename()10. inf…...
MacOS下载钉钉直播回放视频的Python最新解决方案
tags: Python MacOS Tips 写在前面 之前写过一篇关于用Charles抓包下载钉钉直播回放视频的方法, 那会还是可以直接通过FFmpeg下载m3u8链接并且直接合并的, 但是现在直接上FFmpeg会出现403, 所以还是用别的方法来做吧. 后来发现抓包找到的m3u8不是加密视频流, 那就直接下载ts…...
2023年测试人跳槽新功略,涨薪10K+
软件测试是如何实现涨薪的呢?很多人眼中的软件测试岗位可能是简单的,技术含量不是那么高,就是看看需求、看业务、设计文档、然后点一点功能是否实现,再稍微深入一点就是测试下安装部署时会不会出现兼容性问题,以及易用…...
RabbitMQ之Work Queues
Work Queues 工作队列(又称任务队列)的主要思想是避免立即执行资源密集型任务,而不得不等待它完成。相反我们安排任务在之后执行。我们把任务封装为消息并将其发送到队列。在后台运行的工作进程将弹出任务并最终执行作业。当有多个工作线程时,这些工作线程将一起处理这些任务…...
CRM哪家好?这5个CRM管理系统很好用!
CRM哪家好?这5个CRM管理系统很好用! CRM(Customer Relationship Management)即客户关系管理,能够帮助提高客户的价值、满意度、赢利性和忠实度,缩减销售周期和销售成本、增加收入、寻找扩展业务所需的新的市场和渠道,…...
国内ce认证机构有哪些 国内十大CE认证机构排名 做ce认证的公司推荐
CE认证,是任何企业的任何产品走进欧盟市场的硬性要求。挑选CE认证机构,一定要认准拥有正规资质的机构/企业,例如中国质量认证中心CQC、CVC威凯、CTI华测检测,以及TV南德认证、安博检测、万泰认证等。本文中,MaiGoo小编…...
多If函数封装的策略
在工作中我们经常遇到有多个if的判读函数,这是一件很正常的事情,如下: let order function (orderType, isPay, count) {if (orderType 1) {// 充值 500if (isPay true) {// 充值成功console.log(中奖100元)} else {if (count > 0) {c…...
238. 银河英雄传说
Powered by:NEFU AB-IN Link 文章目录238. 银河英雄传说题意思路代码238. 银河英雄传说 题意 有一个划分为 N列的星际战场,各列依次编号为 1,2,…,N 有 N艘战舰,也依次编号为 1,2,…,N,其中第 i号战舰处于第 i列。 有 T条指令,每…...
centos7 开机自启动自定义脚本
centos7 开机自启动自定义脚本背景配置自启动jar1.首先书写自启动脚本2.在rc.local中加入脚本reboot测试docker版本的自启动背景 项目中有遇到2个问题, 1: 使用java启动jar包 2: docker容器中自启动个服务。 这2个都要使用linux的开机自启动问…...
【Linux】动静态库的制作
🌠 作者:阿亮joy. 🎆专栏:《学会Linux》 🎇 座右铭:每个优秀的人都有一段沉默的时光,那段时光是付出了很多努力却得不到结果的日子,我们把它叫做扎根 目录👉动静库和静…...
数据备份学习笔记2
Linux实现本地备份的命令: mkdir -p /root/backup/date "%Y-%m-%d" tar -zcvPf /root/backup/date "%Y-%m-%d"/test20230221.tar.gz /root/test20230221/ 我们再看下tar命令选项: tar -czvf txt3.tar.gz txt3 tar -xvf txt4.tar.g…...
webRTC
WebRTC是一种实时通信技术,可以在浏览器中实现音频、视频和数据的实时传输。WebRTC使用标准的API和协议,如RTCPeerConnection和RTCDataChannel等,可以实现点对点通信和多方会议等多种应用场景。WebRTC可以应用于Web前端、移动端和桌面端等多种…...
用Python搓一个黑洞
文章目录简介单位制观测绘图简介 黑洞图像大家都知道,毕竟前几年刚发布的时候曾火遍全网,甚至都做成表情包了。 问题在于,凭什么认为这就是黑洞的照片,而不是一个甜甜圈啥的给整模糊了得到的呢?有什么理论依据吗&…...
Spring MVC常用功能及注解
目录 一、什么是Spring MVC 1.1 Spring MVC定义 1.2 MVC定义 1.3 MVC和Spring MVC的关系 1.4 Spring MVC的作用 二、Spring MVC的使用 2.1 Spring MVC的创建和连接 2.1.1 RequestMapping注解 2.1.2 GetMapping注解 2.1.3 PostMapping注解 2.2 获取参数 2.2.1 获取单…...
shell 编程
文章目录一、shell 编程1.1. 脚本执行1.2. 变量1.3. 特殊变量1.4. 运算符1.5. for 循环1.6. while 循环1.7. case 语句1.8. read 命令1.9. if 判断1.10. 判断语句1.11. 自定义函数1.12. 脚本调试二、sed2.1. sed 选项2.2. sed function2.3. sed 删除(d 命令…...
Leetcode.1401 圆和矩形是否有重叠
题目链接 Leetcode.1401 圆和矩形是否有重叠 Rating : 1709 题目描述 给你一个以 (radius, xCenter, yCenter)表示的圆和一个与坐标轴平行的矩形 (x1, y1, x2, y2),其中 (x1, y1)是矩形左下角的坐标,而 (x2, y2)是右上角的坐标。 如果圆和矩…...
CHAPTER 3 Web Server - httpd配置(二)
Web Server - httpd配置二3.1 httpd配置3.1.1 基于用户的访问控制3.1.2 basic认证配置示例:1. 添加用户2. 添加网页文件3. 定义安全域4. 修改父目录权限5. 访问效果6. 在配置文件中定义一个".htaccess"隐藏文件7. 添加组3.1.3 虚拟主机1. 构建方案2. 基于…...
【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密
在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...
线程与协程
1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指:像函数调用/返回一样轻量地完成任务切换。 举例说明: 当你在程序中写一个函数调用: funcA() 然后 funcA 执行完后返回&…...
【第二十一章 SDIO接口(SDIO)】
第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...
1688商品列表API与其他数据源的对接思路
将1688商品列表API与其他数据源对接时,需结合业务场景设计数据流转链路,重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点: 一、核心对接场景与目标 商品数据同步 场景:将1688商品信息…...
Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具
文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...
跨链模式:多链互操作架构与性能扩展方案
跨链模式:多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈:模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展(H2Cross架构): 适配层…...
DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI
前一阵子在百度 AI 开发者大会上,看到基于小智 AI DIY 玩具的演示,感觉有点意思,想着自己也来试试。 如果只是想烧录现成的固件,乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外,还提供了基于网页版的 ESP LA…...
解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错
出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上,所以报错,到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本,cu、torch、cp 的版本一定要对…...
(转)什么是DockerCompose?它有什么作用?
一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用,而无需手动一个个创建和运行容器。 Compose文件是一个文本文件,通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...
根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:
根据万维钢精英日课6的内容,使用AI(2025)可以参考以下方法: 四个洞见 模型已经比人聪明:以ChatGPT o3为代表的AI非常强大,能运用高级理论解释道理、引用最新学术论文,生成对顶尖科学家都有用的…...
