python中import学习备忘笔记
发布时间 - 2026-01-10 22:46:18 点击率:次前言

在python的模块有两种组织方式,一种是单纯的python文件,文件名就是模块名,一种是包,包是一个包含了若干python文件的目录,目录下必须有一个文件__init__.py,这样目录名字就是模块名,包里的python文件也可以通过包名.文件名的方式import
import语法
import语法有两种
1、直接import模块
import Module import Module as xx
2、从模块import对象(下级模块,类,函数,变量等)
from Module import Name from Module immport Name as yy
as语法是用来设置对象(这里用对象泛指模块,类,函数等等)别名,import将对象名字引入了当前文件的名字空间
假设有如下目录结构
├── A.py └── pkg ├── B.py └── __init__.py
在当前目录下,以下语句都是有效的
import A import pkg import pkg.B from pkg import B
为了简化讨论,下面将不会对as语法进行举例
import步骤
python所有加载的模块信息都存放在sys.modules结构中,当import一个模块时,会按如下步骤来进行
- 如果是import A,检查
sys.modules中是否已经有A,如果有则不加载,如果没有则为A创建module对象,并加载A - 如果是from A import B,先为A创建module对象,再解析A,从中寻找B并填充到A的
__dict__中
嵌套import
在import模块时我们可能会担心一个模块会不会被import多次,假设有A,B,C三个模块,A需要import B和C,B又要import C,这样A会执行到两次import C,一次是自己本身import,一次是在import B时执行的import,但根据上面讲到的import步骤,在第二次import时发现模块已经被加载,所以不会重复import
但如下情况却会报错
#filename: A.py from B import BB class AA:pass #filename: B.py from A import AA class BB:pass
这时不管是执行A.py还是B.py都会抛出ImportError的异常,假设我们执行的是A.py,究其原因如下
- 文件A.py执行from B import BB,会先扫描B.py,同时在A的名字空间中为B创建module对象,试图从B中查找BB
- 扫描B.py第一行执行
from A import AA,此时又会去扫描A.py - 扫描A.py第一行执行
from B import BB,由于步骤1已经为B创建module对象,所以会直接从B的module对象的__dict__中获取BB,此时显然BB是获取不到的,于是抛出异常
解决这种情况有两种办法,
- 将from B import BB改为import B,或将from A import AA改为import A
- 将A.py或B.py中的两行代码交换位置
总之,import需要注意的是,尽量在需要用到时再import
包的import
当一个目录下有__init__.py文件时,该目录就是一个python的包
import包和import单个文件是一样的,我们可以这样类比:
- import单个文件时,文件里的类,函数,变量都可以作为import的对象
- import包时,包里的子包,文件,以及
__init__.py里的类,函数,变量都可以作为import的对象
假设有如下目录结构
pkg ├── __init__.py └── file.py
其中__init__.py内容如下
argument = 0 class A:pass
在和pkg同级目录下执行如下语句都是OK的
>>> import pkg >>> import pkg.file >>> from pkg import file >>> from pkg import A >>> from pkg import argument
但如下语句是错误的
>>> import pkg.A >>> import pkg.argument
报错ImportError: No module named xxx,因为当我们执行import A.B,A和B都必须是模块(文件或包)
相对导入和绝对导入
绝对导入的格式为import A.B或from A import B,相对导入格式为from . import B或from ..A import B,.代表当前模块,..代表上层模块,...代表上上层模块,依次类推。当我们有多个包时,就可能有需求从一个包import另一个包的内容,这就会产生绝对导入,而这也往往是最容易发生错误的时候,还是以具体例子来说明
目录结构如下
app ├── __inti__.py ├── mod1 │ ├── file1.py │ └── __init__.py ├── mod2 │ ├── file2.py │ └── __init__.py └── start.py
其中app/start.py内容为import mod1.file1
app/mod1/file1.py内容为from ..mod2 import file2
为了便于分析,我们在所有py文件(包括__init__.py)第一行加入print __file__, __name__
现在app/mod1/file1.py里用到了相对导入,我们在app/mod1下执行python file1.py或者在app下执行python mod1/file1.py都会报错ValueError: Attempted relative import in non-package
在app下执行python -m mod1.file1或python start.py都会报错ValueError: Attempted relative import beyond toplevel package
具体原因后面再说,我们先来看一下导入模块时的一些规则
在没有明确指定包结构的情况下,python是根据__name__来决定一个模块在包中的结构的,如果是__main__则它本身是顶层模块,没有包结构,如果是A.B.C结构,那么顶层模块是A。
基本上遵循这样的原则
- 如果是绝对导入,一个模块只能导入自身的子模块或和它的顶层模块同级别的模块及其子模块
- 如果是相对导入,一个模块必须有包结构且只能导入它的顶层模块内部的模块
有目录结构如下
A ├── B1 │ ├── C1 │ │ └── file.py │ └── C2 └── B2
其中A,B1,B2,C1,C2都为包,这里为了展示简单没有列出__init__.py文件,当file.py的包结构为A.B1.C1.file(注意,是根据__name__来的,而不是磁盘的目录结构,在不同目录下执行file.py时对应的包目录结构都是不一样的)时,在file.py中可采用如下的绝对的导入
import A.B1.C2 import A.B2
和如下的相对导入
from .. import C2 from ... import B2
什么情况下会让file.py的包结构为A.B1.C1.file呢,有如下两种
- 在A的上层目录执行
python -m A.B1.C1.file, 此时明确指定了包结构 - 在A的上层目录建立文件start.py,在
start.py里有import A.B1.C1.file,然后执行python start.py,此时包结构是根据file.py的__name__变量来的
再看前面出错的两种情况,第一种执行python file1.py和python mod1/file1.py,此时file.py的__name__为__main__ ,也就是说它本身就是顶层模块,并没有包结构,所以会报错
第二种情况,在执行python -m mod1.file1和python start.py时,前者明确告诉解释器mod1是顶层模块,后者需要导入file1,而file1.py的__name__为mod1.file1,顶层模块为也mod1,所以在file1.py中执行from ..mod2 import file2时会报错 ,因为mod2并不在顶层模块mod1内部。通过错误堆栈可以看出,并不是在start.py中绝对导入时报错,而是在file1.py中相对导入报的错
那么如何才能偶正确执行呢,有两种方法,一种是在app上层目录执行python -m app.mod1.file1,另一种是改变目录结构,将所有包放在一个大包中,如下
app ├── pkg │ ├── __init__.py │ ├── mod1 │ │ ├── __init__.py │ │ └── file1.py │ └── mod2 │ ├── __init__.py │ └── file2.py └── start.py
start.py内容改成import pkg.mod1.file1,然后在app下执行python start.py
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家学习或者使用python能带来一定的帮助,如有疑问大家可以留言交流。
# import
# 在python
# python中
# import是什么
# python
# py文件
# Python中循环引用(import)失败的解决方法
# python之import机制详解
# 跟老齐学Python之Import 模块
# Python import自定义模块方法
# python在不同层级目录import模块的方法
# python 环境变量和import模块导入方法(详解)
# 浅谈python import引入不同路径下的模块
# 详解Python import方法引入模块的实例
# Python中import机制详解
# python学习基础之循环import及import过程
# 报错
# 是在
# 都是
# 有两种
# 目录下
# 的是
# 加载
# 放在
# 两种
# 当我们
# 抛出
# 包里
# 格式为
# 它本身
# 包中
# 是一个
# 情况下
# 多个
# 如有
# 会不会
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
Laravel怎么进行数据库事务处理_Laravel DB Facade事务操作确保数据一致性
JS中使用new Date(str)创建时间对象不兼容firefox和ie的解决方法(两种)
如何用PHP快速搭建高效网站?分步指南
Laravel如何使用Eloquent ORM进行数据库操作?(CRUD示例)
Laravel如何使用Vite进行前端资源打包?(配置示例)
怎么用AI帮你为初创公司进行市场定位分析?
Laravel中间件起什么作用_Laravel Middleware请求生命周期与自定义详解
如何快速搭建高效WAP手机网站吸引移动用户?
公司门户网站制作公司有哪些,怎样使用wordpress制作一个企业网站?
实例解析Array和String方法
黑客如何通过漏洞一步步攻陷网站服务器?
大连网站制作公司哪家好一点,大连买房网站哪个好?
Windows驱动无法加载错误解决方法_驱动签名验证失败处理步骤
Win11怎么设置默认图片查看器_Windows11照片应用关联设置
英语简历制作免费网站推荐,如何将简历翻译成英文?
,怎么在广州志愿者网站注册?
android nfc常用标签读取总结
linux top下的 minerd 木马清除方法
如何在VPS电脑上快速搭建网站?
Laravel怎么在Blade中安全地输出原始HTML内容
Laravel如何使用Sanctum进行API认证?(SPA实战)
如何在腾讯云免费申请建站?
打开php文件提示内存不足_怎么调整php内存限制【解决方案】
Python自然语言搜索引擎项目教程_倒排索引查询优化案例
javascript中对象的定义、使用以及对象和原型链操作小结
Laravel项目结构怎么组织_大型Laravel应用的最佳目录结构实践
如何彻底卸载建站之星软件?
Laravel怎么配置.env环境变量_Laravel生产环境敏感数据保护与读取【方法】
Laravel与Inertia.js怎么结合_使用Laravel和Inertia构建现代单页应用
Laravel事件和监听器如何实现_Laravel Events & Listeners解耦应用的实战教程
nodejs redis 发布订阅机制封装实现方法及实例代码
html5audio标签播放结束怎么触发事件_onended回调方法【教程】
Python制作简易注册登录系统
Laravel如何使用Service Container和依赖注入?(代码示例)
Laravel如何获取当前登录用户信息_Laravel Auth门面使用与Session用户读取【技巧】
如何在万网ECS上快速搭建专属网站?
高性能网站服务器配置指南:安全稳定与高效建站核心方案
轻松掌握MySQL函数中的last_insert_id()
香港服务器网站生成指南:免费资源整合与高速稳定配置方案
Laravel如何配置Horizon来管理队列?(安装和使用)
关于BootStrap modal 在IOS9中不能弹出的解决方法(IOS 9 bootstrap modal ios 9 noticework)
Laravel如何使用模型观察者?(Observer代码示例)
Win11任务栏卡死怎么办 Windows11任务栏无反应解决方法【教程】
详解Nginx + Tomcat 反向代理 负载均衡 集群 部署指南
如何正确选择百度移动适配建站域名?
Laravel怎么实现一对多关联查询_Laravel Eloquent模型关系定义与预加载【实战】
详解jQuery停止动画——stop()方法的使用
如何在Ubuntu系统下快速搭建WordPress个人网站?
Laravel如何为API生成Swagger或OpenAPI文档
齐河建站公司:营销型网站建设与SEO优化双核驱动策略

