当前位置: 首页 > news >正文

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 的加载过程:

  1. 先从 sys.modules 中查看是否有导入的模块,有,则获取该模块,并加入到当前的全局变量中。
  2. 如果 sys.modules 中没有需要导入的模块,则按照 sys.path 中的目录路径进行搜索找到对应的模块文件再加载到 module 对象中返回。

相关文章:

python中import原理

0. 前言 在 python 中引入 Module 是再常见不过了&#xff0c;那么当我们 import 时它做了什么事情呢&#xff1f;它是如何加载 Module 使用的呢&#xff1f; 1. 什么是 module&#xff1f; 一般&#xff0c;Module 是一个后缀为 .py 的文件&#xff0c;其 module 名称一般…...

《Qt6开发及实例》6-4 显示SVG格式图片

目录 一、简介与设计 1.1 简介 1.2 设计 二、SvgWidget 2.1 鼠标滚轮事件 三、svgwindow 四、MainWindow 一、简介与设计 1.1 简介 1、SVG 的英文全称是 Scalable Vector Graphics&#xff0c;即可缩放的矢量图形。它是由万维网联盟&#xff08;W3C&#xff09;在 200…...

OpenGL ES 绘制一张图片

GLSL 语法与内建函数 GLSL 的修饰符与数据类型 GLSL 中变量的修饰符 const&#xff1a;修饰不可被外界改变的常量attribute&#xff1a;修饰经常更改的变量&#xff0c;只可以在顶点着色器中使用uniform&#xff1a;修饰不经常更改的变量&#xff0c;可用于顶点着色器和片段…...

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+

软件测试是如何实现涨薪的呢&#xff1f;很多人眼中的软件测试岗位可能是简单的&#xff0c;技术含量不是那么高&#xff0c;就是看看需求、看业务、设计文档、然后点一点功能是否实现&#xff0c;再稍微深入一点就是测试下安装部署时会不会出现兼容性问题&#xff0c;以及易用…...

RabbitMQ之Work Queues

Work Queues 工作队列(又称任务队列)的主要思想是避免立即执行资源密集型任务,而不得不等待它完成。相反我们安排任务在之后执行。我们把任务封装为消息并将其发送到队列。在后台运行的工作进程将弹出任务并最终执行作业。当有多个工作线程时,这些工作线程将一起处理这些任务…...

CRM哪家好?这5个CRM管理系统很好用!

CRM哪家好&#xff1f;这5个CRM管理系统很好用&#xff01; CRM(Customer Relationship Management)即客户关系管理&#xff0c;能够帮助提高客户的价值、满意度、赢利性和忠实度&#xff0c;缩减销售周期和销售成本、增加收入、寻找扩展业务所需的新的市场和渠道&#xff0c;…...

国内ce认证机构有哪些 国内十大CE认证机构排名 做ce认证的公司推荐

CE认证&#xff0c;是任何企业的任何产品走进欧盟市场的硬性要求。挑选CE认证机构&#xff0c;一定要认准拥有正规资质的机构/企业&#xff0c;例如中国质量认证中心CQC、CVC威凯、CTI华测检测&#xff0c;以及TV南德认证、安博检测、万泰认证等。本文中&#xff0c;MaiGoo小编…...

多If函数封装的策略

在工作中我们经常遇到有多个if的判读函数&#xff0c;这是一件很正常的事情&#xff0c;如下&#xff1a; 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列的星际战场&#xff0c;各列依次编号为 1,2,…,N 有 N艘战舰&#xff0c;也依次编号为 1,2,…,N&#xff0c;其中第 i号战舰处于第 i列。 有 T条指令&#xff0c;每…...

centos7 开机自启动自定义脚本

centos7 开机自启动自定义脚本背景配置自启动jar1.首先书写自启动脚本2.在rc.local中加入脚本reboot测试docker版本的自启动背景 项目中有遇到2个问题&#xff0c; 1&#xff1a; 使用java启动jar包 2&#xff1a; docker容器中自启动个服务。 这2个都要使用linux的开机自启动问…...

【Linux】动静态库的制作

​&#x1f320; 作者&#xff1a;阿亮joy. &#x1f386;专栏&#xff1a;《学会Linux》 &#x1f387; 座右铭&#xff1a;每个优秀的人都有一段沉默的时光&#xff0c;那段时光是付出了很多努力却得不到结果的日子&#xff0c;我们把它叫做扎根 目录&#x1f449;动静库和静…...

数据备份学习笔记2

Linux实现本地备份的命令&#xff1a; mkdir -p /root/backup/date "%Y-%m-%d" tar -zcvPf /root/backup/date "%Y-%m-%d"/test20230221.tar.gz /root/test20230221/ 我们再看下tar命令选项&#xff1a; tar -czvf txt3.tar.gz txt3 tar -xvf txt4.tar.g…...

webRTC

WebRTC是一种实时通信技术&#xff0c;可以在浏览器中实现音频、视频和数据的实时传输。WebRTC使用标准的API和协议&#xff0c;如RTCPeerConnection和RTCDataChannel等&#xff0c;可以实现点对点通信和多方会议等多种应用场景。WebRTC可以应用于Web前端、移动端和桌面端等多种…...

用Python搓一个黑洞

文章目录简介单位制观测绘图简介 黑洞图像大家都知道&#xff0c;毕竟前几年刚发布的时候曾火遍全网&#xff0c;甚至都做成表情包了。 问题在于&#xff0c;凭什么认为这就是黑洞的照片&#xff0c;而不是一个甜甜圈啥的给整模糊了得到的呢&#xff1f;有什么理论依据吗&…...

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 删除&#xff08;d 命令&#xf…...

Leetcode.1401 圆和矩形是否有重叠

题目链接 Leetcode.1401 圆和矩形是否有重叠 Rating &#xff1a; 1709 题目描述 给你一个以 (radius, xCenter, yCenter)表示的圆和一个与坐标轴平行的矩形 (x1, y1, x2, y2)&#xff0c;其中 (x1, y1)是矩形左下角的坐标&#xff0c;而 (x2, y2)是右上角的坐标。 如果圆和矩…...

CHAPTER 3 Web Server - httpd配置(二)

Web Server - httpd配置二3.1 httpd配置3.1.1 基于用户的访问控制3.1.2 basic认证配置示例&#xff1a;1. 添加用户2. 添加网页文件3. 定义安全域4. 修改父目录权限5. 访问效果6. 在配置文件中定义一个".htaccess"隐藏文件7. 添加组3.1.3 虚拟主机1. 构建方案2. 基于…...

Python控制台输出彩色字体指南

在Python开发中&#xff0c;有时我们需要在控制台输出彩色文本以提高可读性或创建更友好的用户界面。本文将介绍如何使用colorama库来实现这一功能。 为什么需要彩色输出&#xff1f; 提高可读性&#xff1a;重要信息可以用不同颜色突出显示更好的用户体验&#xff1a;错误信息…...

零基础在实践中学习网络安全-皮卡丘靶场(第十六期-SSRF模块)

最后一期了&#xff0c;感谢大家一直以来的关注&#xff0c;如果您对本系列文章内容有问题或者有更好的方法&#xff0c;请在评论区发送。 介绍 其形成的原因大都是由于服务端提供了从其他服务器应用获取数据的功能,但又没有对目标地址做严格过滤与限制导致攻击者可以传入任意…...

YOLOv8n行人检测实战:从数据集准备到模型训练

YOLOv8n行人检测实战&#xff1a;从数据集准备到模型训练 一、为什么选择YOLOv8&#xff1f;二、环境准备2.1 环境配置解析 三、安装Ultralytics框架四、数据集准备与理解4.1 数据集下载4.2 数据集结构4.3 YOLO标签格式解析 五、数据集可视化&#xff1a;理解标注数据5.1 可视化…...

深度学习环境配置指南:基于Anaconda与PyCharm的全流程操作

一、环境搭建前的准备 1. 查看基础环境位置 conda env list 操作说明&#xff1a;通过该命令确认Anaconda默认环境&#xff08;base&#xff09;所在磁盘路径&#xff08;如D盘&#xff09;&#xff0c;后续操作需跳转至该磁盘根目录。 二、创建与激活独立虚拟环境 1. 创…...

SQLServer中的存储过程与事务

一、存储过程的概念 1. 定义 存储过程&#xff08;Stored Procedure&#xff09;是一组预编译的 SQL 语句的集合&#xff0c;它们被存储在数据库中&#xff0c;可以通过指定存储过程的名称并执行来调用它们。存储过程可以接受输入参数、输出参数&#xff0c;并且可以返回执行…...

day45python打卡

知识点回顾&#xff1a; tensorboard的发展历史和原理tensorboard的常见操作tensorboard在cifar上的实战&#xff1a;MLP和CNN模型 效果展示如下&#xff0c;很适合拿去组会汇报撑页数&#xff1a; 作业&#xff1a;对resnet18在cifar10上采用微调策略下&#xff0c;用tensorbo…...

【反无人机检测】C2FDrone:基于视觉Transformer网络的无人机间由粗到细检测

C2FDrone&#xff1a;基于视觉Transformer网络的无人机间由粗到细检测 C2FDrone: Coarse-to-Fine Drone-to-Drone Detection using Vision Transformer Networks 论文链接 摘要 摘要——基于视觉的无人机间检测系统在碰撞规避、反制敌对无人机和搜救行动等应用中至关重要。然…...

撰写脚本,通过发布/joint_states话题改变机器人在Rviz中的关节角度

撰写脚本&#xff0c;通过发布/joint_states话题改变机器人在Rviz中的关节角度 提问 为我写一个改变关节base_spherical_center_high_joint角度的python脚本吧。适用于ROS2的humble 回答 下面是一个适用于 ROS 2 Humble 的 Python 脚本&#xff0c;它会以指定频率持续发布 …...

智能推荐系统:协同过滤与深度学习结合

智能推荐系统&#xff1a;协同过滤与深度学习结合 系统化学习人工智能网站&#xff08;收藏&#xff09;&#xff1a;https://www.captainbed.cn/flu 文章目录 智能推荐系统&#xff1a;协同过滤与深度学习结合摘要引言技术原理对比1. 协同过滤算法&#xff1a;基于相似性的推…...

Leetcode 1892. 页面推荐Ⅱ

1.题目基本信息 1.1.题目描述 表&#xff1a; Friendship ---------------------- | Column Name | Type | ---------------------- | user1_id | int | | user2_id | int | ---------------------- (user1_id,user2_id) 是 Friendship 表的主键(具有唯一值的列的组合…...