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. 基于…...
机器学习与深度学习在地球物理勘探中的应用:基于电阻率数据预测极化率模型
1. 项目概述与核心价值在花岗岩这类地质条件复杂的地区搞勘探,最头疼的就是地下情况“看不清”。传统的电阻率(ERT)和激发极化(IP)联合反演,就像用一把刻度模糊的尺子去量一块表面坑洼不平的石头——面对高…...
ARM指令追踪技术及TRCVICTLR寄存器详解
1. ARM指令追踪技术概述在嵌入式系统开发和调试过程中,指令追踪(Instruction Trace)是一项至关重要的技术。它通过硬件机制记录处理器的执行流程,为开发者提供程序运行的完整轨迹。ARM架构从v7开始引入嵌入式跟踪宏单元࿰…...
用数字逻辑门复刻柏林钟:从二进制编码到硬件实现
1. 项目概述:用数字电路复刻“柏林钟”作为一个在柏林长大的孩子,我从小就对库达姆大街上的那座“柏林钟”着迷。它不像传统时钟那样用指针或数字告诉你时间,而是通过几排不同颜色的发光方块,以一种近乎艺术的方式呈现时间。这种独…...
告别外部中断!用EnableInterrupt库轻松搞定Arduino Nano多通道PWM读取(附完整代码)
Arduino Nano多通道PWM读取实战:用EnableInterrupt突破硬件限制当你用Arduino Nano开发四轴飞行器或机器人项目时,是否遇到过这样的尴尬:遥控器的四个通道PWM信号需要同时读取,但Nano只有两个外部中断引脚?这个问题困扰…...
如何进行TVA仿真引擎的“光照地狱”训练?
重磅预告:本专栏将独家连载系列丛书《智能体视觉技术与应用》部分精华内容,该书是世界首套系统阐述“因式智能体”视觉理论与实践的专著,特邀美国 TypeOne 公司首席科学家、斯坦福大学博士 Bohan 担任技术顾问。Bohan先生师从美国三院院士、“…...
轻量化部署,异地机房快速接入,多机房管理不用再大动干戈
随着业务拓展,不少企业、单位陆续建起异地分部机房、多区域节点机房。传统资产管理系统部署复杂、对接困难,异地机房接入成本高、周期长,改造繁琐,让很多运维团队望而却步,只能继续沿用分散人工管理,资产混…...
skills CANN开源社区贡献技能包开发指南
前言 开源社区的健康运转,不仅依赖核心代码的贡献,还需要降低贡献门槛、提供清晰的指南和自动化工具。skills仓库是CANN开源社区的"贡献技能包",提供了一系列辅助脚本、代码模板、CI检查和文档生成工具,帮助新手快速上…...
AI算力要上天?别笑,太空数据中心真能干翻地球电费!
前言你有没有算过,训练一个大模型,相当于烧掉多少吨煤?如今AI狂飙突进,算力需求指数级增长,可地球上的电——不够用了!更别说建个数据中心还得跟地方政府“斗智斗勇”,抢地皮、配储能、扛审批&a…...
电信运营商每月处理海量工单,如何不再出错?基于AI Agent的端到端自动化解决方案
在2026年的电信行业,海量工单处理已不再仅仅是效率问题,而是合规与生存的底线。随着2026年5月20日《电信和互联网服务 基础电信企业网上营业厅服务规范》国家标准的正式实施,监管层对“信息透明、流程闭环、计费精准”的要求达到了前所未有的…...
举一个具体例子说明为什么索引不是越多越好,举具体字段
文章目录1. 核心舞台:笔记表 (t_note) 结构设计🚨 错误的操作:2. 结合具体字段,拆解三大翻车现场现场一:给 view_count(浏览量)加索引 —— 导致写放大,拖垮数据库现场二:…...
