我 的 个 人 主 页:👉👉 失心疯的个人主页 👈👈
入 门 教 程 推 荐 :👉👉 Python零基础入门教程合集 👈👈
虚 拟 环 境 搭 建 :👉👉 Python项目虚拟环境(超详细讲解) 👈👈
PyQt5 系 列 教 程:👉👉 Python GUI(PyQt5)文章合集 👈👈
Oracle数据库教程:👉👉 Oracle数据库文章合集 👈👈
优 质 资 源 下 载 :👉👉 资源下载合集 👈👈
import 模块名
import 包名.模块名
import 包名.子包名.模块名
# 如果是某个包里面的模块,可以通过点语法来定位
# 导入多层级包里面的模块,会分别执行每一级包里面的__init__.py文件
# 方式1
import 模块名1
import 模块名2
# 方式2
import 模块名1, 模块名2
import 模块名1, 包名.子包名.模块名2
import 模块名 as 别名
import 包名.子包名.模块名 as 别名
# 后续使用可以直接通过 别名.方法名() / 别名.属性 使用
# 不起别名
import 包名.子包名.模块名
print(包名.子包名.模块名.属性1) # 不起别名,使用时,前缀太长太复杂
print(包名.子包名.模块名.属性2)
print(包名.子包名.模块名.属性3)
# 起别名
import 包名.子包名.模块名 as m
print(m.属性1) # 起别名后,使用时,简单
print(m.属性2)
print(m.属性3)
# 根据文件后缀调用不同模块,对文件进行打开、读取、关闭操作
# 不起别名
if file_extension == 'txt':
import txt_parse
txt_parse.open()
txt_parse.read()
txt_parse.close()
elif file_extension == 'doc':
import doc_parse
doc_parse.open()
doc_parse.read()
doc_parse.close()
# 这里不同的文件类型,对文件的打开、读取、关闭操作都是一样的,仅仅是使用的模块不同
# 起别名
if file_extension == 'txt':
import txt_parse as p
elif file_extension == 'doc':
import doc_parse as p
p.open()
p.read()
p.close()
# 整个代码就可以将文件的打开、读取、关闭操作进行提取整合,减少代码冗余
import
导入包和模块,在使用包和模块内部资源时,需要指明资源的包和模块名称包名.子包名.模块.属性
、包名.子包名.模块.方法()
import 包名
的方式导入一个包,默认不会导入任何模块__init__.py
文件,所以可以在__init__.py
文件中再次导入需要的模块
这里导入模块的时候需要写明模块的绝对路径,是因为模块检索路径的问题,后续会讲
from....import....
的形式导入作用
语法
from A import B[ as 别名]
# 从A导入B资源到当前位置
最终组合
语法
# 导入单个模块
from 包 import 模块
# 导入多个模块
from 包 import 模块1, 模块2
# 起别名
from 包 import 模块 as 别名
from 包 import 模块1 as 别名1, 模块2 as 别名2
# 包有多层级
from 包.子包 import 模块
# 使用模块资源
模块.资源
# 导入单个资源
from 模块 import 资源
# 导入多个资源
from 模块 import 资源1, 资源2
# 起别名
from 模块 import 资源 as 别名
from 模块 import 资源1 as 别名1, 资源2 as 别名2
# 模块有多层级
from 包.模块 import 资源
# 使用资源
资源
示例
先创建几个简单的模块
# host_module1.py
h_m1_num1 = 100
h_m1_num2 = 199
# host_module2.py
h_m1_num1 = 200
h_m1_num2 = 299
# sub_module1.py
s_m1_num1 = 1100
s_m1_num2 = 1199
# sub_module2.py
s_m2_num1 = 2100
s_m2_num2 = 2199
通过test.py
分别导入这些模块
# 导入单个模块
from host_package import host_module1
print(host_module1.h_m1_num1) # 100
print(host_module1.h_m1_num2) # 199
# 导入多个模块
from host_package import host_module1, host_module2
print(host_module1.h_m1_num1) # 100
print(host_module1.h_m1_num2) # 199
print(host_module2.h_m2_num1) # 200
print(host_module2.h_m2_num2) # 299
# 起别名1
from host_package import host_module1 as hm1
print(hm1.h_m1_num1) # 100
print(hm1.h_m1_num2) # 199
# 起别名2
from host_package import host_module1 as hm1, host_module2 as hm2
print(hm1.h_m1_num1) # 100
print(hm1.h_m1_num2) # 199
print(hm2.h_m2_num1) # 200
print(hm2.h_m2_num2) # 299
# 包有多层级
from host_package.sub_package import sub_module1
print(sub_module1.s_m1_num1) # 1100
print(sub_module1.s_m1_num2) # 1199
from host_package.sub_package import sub_module1, sub_module2
print(sub_module1.s_m1_num1) # 1100
print(sub_module1.s_m1_num2) # 1199
print(sub_module2.s_m2_num1) # 2100
print(sub_module2.s_m2_num2) # 2199
from host_package.sub_package import sub_module1 as sm1, sub_module2 as sm2
print(sm1.s_m1_num1) # 1100
print(sm1.s_m1_num2) # 1199
print(sm2.s_m2_num1) # 2100
print(sm2.s_m2_num2) # 2199
# 错误演示
from host_package import sub_package.sub_module1
print(sub_package.sub_module1.s_m1_num1)
# ========== 输出结果 ==========
# File "E:\StudyCode\Python\15-包和模块\test.py", line 44
# from host_package import sub_package.sub_module1
# ^
# SyntaxError: invalid syntax
test.py
文件位置,与host_module1.py
模块在同一级目录# 导入单个资源
from host_module1 import h_m1_num1
print(h_m1_num1) # 100
# print(h_m1_num2) # 报错:NameError: name 'h_m1_num2' is not defined
# 导入多个资源
from host_module1 import h_m1_num1, h_m1_num2
print(h_m1_num1) # 100
print(h_m1_num2) # 199
# 起别名1
from host_module1 import h_m1_num1 as hm1
print(hm1) # 100
# 起别名2
from host_module1 import h_m1_num1 as hm1, h_m1_num2 as hm2
print(hm1) # 100
print(hm2) # 199
# 模块有多层级
from sub_package.sub_module1 import s_m1_num1
print(s_m1_num1) # 1100
from sub_package.sub_module1 import s_m1_num1, s_m1_num2
print(s_m1_num1) # 1100
print(s_m1_num2) # 1199
# 错误演示
from sub_package import sub_module1.s_m1_num1
print(sub_module1.s_m1_num1)
# ========== 输出结果 ==========
# File "E:\StudyCode\Python\15-包和模块\host_package\test.py", line 85
# from sub_package import sub_module1.s_m1_num1
# ^
# SyntaxError: invalid syntax
注意
from A import B
保证B部分路径最简,从哪里能看到谁才能导入谁from 大包 import 小包.模块
import
后面没有做到路径最简化from 大包.小包 import 模块
from 包 import 模块.资源
import
后面没有做到路径最简化from 包.模块 import 资源
导入特例
from 模块 import *
import *
并不是导入模块中的所有资源,而是导入模块中__all__
变量指定的资源# other.py
num1 = 100
num2 = 200
num3 = 300
num4 = 400
__all__ = ['num1', 'num2', 'num4']
# test.py文件
from other import *
# 这里 import * 仅仅只是导入了__all__变量指定的num1、num2和num4
print(num1)
print(num2)
print(num4)
from 包 import *
import *
并不是导入包中所有的模块资源,而是导入包中__init__.py
文件中__all__
变量指定的模块import *
这种方式慎用
__all__
变量指明资源,那么就会导入包里面所有模块和模块中所有公有资源第一次导入时
import
后面的变量名称引入到import
语句所在位置的当前命名空间示例讲解
other.py
文件num1 = 100
num2 = 200
def run():
num3 = 300
print(num1)
test.py
文件import other
第二次导入时
结论
import
和from
两种导入方式都会大致执行以上的步骤import other
# other-模块 ————begin
# other-模块 ————end
from other import num1
# other-模块 ————begin
# other-模块 ————end
other.py
文件import
会将other
对象的所有资源都拿到当前命名空间中来用from
仅仅是将other
对象的num1
资源拿到当前命名空间中来用sys.path
中记录的路径按顺序中去搜索sys.modules
sys.path
中的路径
sys.path
路径构成1、当前目录
2、环境变量PYTHONPATH中指定的路径列表
3、Python安装路径
4、Python安装路径下的.pth文件中的文件路径列表
5、Python安装路径的lib库
6、Python安装路径的lib库中.pth文件中的文件路径列表
sys.path
追加路径的方式
sys.path
(仅作用于本次)import sys
sys.path.append('指定路径') # 将指定路径添加到sys.path列表的最后
sys.path.insert(index, '指定路径') # 将指定路径添加到列表的指定索引位置
import 指定模块
# 模块的查找顺序最终根据sys.path列表中路径的位置而定
# 添加环境变量 PYTHONPATH(仅能在cmd中通过python环境执行)
# 此电脑 —— 属性 —— 高级系统设置 —— 环境变量
# 添加到 用户变量, 仅当前用户可用
# 添加到 系统变量, 所有用户均可用
# 配置PyCharm
# PyCharm —— File —— Settings —— Project:xxxx —— Python Interpreter —— 右侧设置按钮 —— Show All... —— Show paths for the selected interpreter —— “+” 把路径添加进去
# 查看.pth文件存放目录
import site
print(site.getsitepackages())
# ['E:\\StudyCode\\Python\\.venv', 'E:\\StudyCode\\Python\\.venv\\lib\\site-packages']
# 创建.pth文件:新建文本文档——将.txt后缀改成.pth
# 将路径添加到.pth文件中
# 再将.pth文件添加到上面查询到的.pth文件存放目录
# 查看已加载模块
import sys
print(sys.modules)
def
、class
、模块会产生单独的命名空间,if
、for
语句不会from...import...
指明绝对路径进行导入加入有两个模块A和B,模块A内导入了模块B,模块B内又导入了模块A,这样就造成了循环导入
场景
test.py
文件
t1 = 'T1'
t2 = 'T2'
import other
print(other.o1)
print(other.o2)
other.py
文件
o1 = 'O1'
o2 = 'O2'
import test
print(test.t1)
print(test.t2)
输出结果
O1
O2
T1
T2
O1
O2
图解
*
循环导入
执行test.py文件
1:增加属性t1、t2
2:导入模块other
2-1:先到sys.modules中查找,未找到
2-2:再根据sys.path路径进行查找
2-3:找到other模块,将other添加到sys.modules中
2-4:执行other模块,给other增加属性o1、o2
2-5:导入test模块
2-5-1:先到sys.modules中查找,未找到
2-5-2:再根据sys.path路径进行查找
2-5-3:找到test模块,将other添加到sys.modules中
2-5-4:执行test模块,给other增加属性t1、t2
2-5-5:导入other模块
2-5-5-1:先到sys.modules中查找,找到了
2-5-5-2:第二次导入other模块,不再执行文件
2-5-6:导入other模块完成,继续往下执行
2-5-7:输出o1、o2,打印O1、O2
2-6:导入test模块完成,继续往下执行
2-7:输出t1、t2,打印T1、T2
3:导入other模块完成,继续往下执行
4:输出o1、o2,打印O1、O2
try:
import other2 as o
except ModuleNotFoundError:
import other as o
print(o.name)
python相对导入与绝对导入,这两个概念是相对于包内导入而言额
包内导入即是包内的模块导入包内部的模块
绝对导入
sys.path
路径进行检索import a
from b import a
相对导入
.
来替代相对路径. # 根据模块名称获取的当前目录
.. # 根据模块名称获取的上级目录
from . import a
from .. import a
.
和..
并不是简单的指代当前文件的当前目录和上级目录通过示例演示
文件结构
sub_module2.py
文件
s2_m1 = 'sub2-1'
s2_m2 = 'sub2-2'
sub_module1.py
文件
import sub_module2
print(sub_module2.s2_m1)
print(sub_module2.s2_m2)
执行sub_module1.py
文件时,能正常导入sub_module2
模块,并执行
# ========== 输出结果 ==========
sub2-1
sub2-2
当我们在上一层目录的module1.py
文件中导入sub_module1
模块时,执行居然会报错…
import sub_package.sub_module1
# from sub_package import sub_module1
# 这两种导入方式是一样的效果,都是绝对导入
# ========== 输出结果 ==========
Traceback (most recent call last):
File "E:\StudyCode\Python\15-包和模块\包内导入\module1.py", line 1, in <module>
import sub_package.sub_module1
File "E:\StudyCode\Python\15-包和模块\包内导入\sub_package\sub_module1.py", line 2, in <module>
import sub_module2
ModuleNotFoundError: No module named 'sub_module2'
这里报错:没有名称是sub_module2
的模块,为什么直接执行sub_module1
的时候能正常导入sub_module2
模块,现在执行module1.py
文件导入sub_module1
模块,再在sub_module1
模块内导入sub_module2
模块就会报错呢?
报错原因
1、import a
和from b import a
两种导入语法都是绝对导入,模块检索路径由sys.path
觉得
2、当执行module1.py
文件时,就确定了sys.path
里面的路径了,后面基本不会再改变
> 执行 module1.py 文件时会将文件当前目录添加到 sys.path 路径中
> 导入 sub_module1 模块时,会执行内部的全部代码,内部需要再导入 sub_module2 模块
> 此时,需要到 sys.path 路径中去搜索 sub_module2 模块
> 但是,在执行 module1 文件时,就确定了 sys.path 路径,仅仅是将 包内导入 目录添加到了路径中
> 并没有将 sub_package 目录添加到路径中,所以通过 import sub_module2 导入模块会因为搜索不到模块而报错
修改文件代码,跟踪sys.path
数据
sub_module1.py
文件
import sys
print('sub_module1:', sys.path)
# import sub_module2
#
# print(sub_module2.s2_m1)
# print(sub_module2.s2_m2)
module1.py
文件
import sub_package.sub_module1
# from sub_package import sub_module1
import sys
print('')
print('module1:', sys.path)
通过跟踪sys.path
的情况
解决办法:使用相对导入
sub_module1.py
文件代码from . import sub_module2
print(sub_module2.s2_m1)
print(sub_module2.s2_m2)
关于.
和..
的说明
.
和..
并不是简单的获取当前文件的目录以及当前文件的上一级目录sub_module1.py
文件代码# from . import sub_module2
# print(sub_module2.s2_m1)
# print(sub_module2.s2_m2)
print('sub_module1:', __name__)
# ========== 输出结果 ==========
sub_module1: __main__
__main__
module1.py
文件代码import sub_package.sub_module1
# from sub_package import sub_module1
print('module1:', __name__)
module1.py
文件,输出结果如下# ========== 输出结果 ==========
sub_module1: sub_package.sub_module1
module1: __main__
module1.py
文件时,通过导入sub_module1
模块的方式执行模块内部的代码时sub_module1
模块的名称变成了sub_package.sub_module1
关于模块名称的问题
__name__
则是main
import
语句导入执行时,当前模块的名称__name__
则是由加载路径决定:包名.子包名.模块名
(这个名称最前面部分则被称为顶级名称)当我们执行module1.py
文件时,通过导入sub_module1
模块的方式执行模块内部的代码时sub_module1
模块的名称变成了sub_package.sub_module1
我们来解析一下sub_module1
模块中的导入语句
from . import sub_module2
# 此时 sub_module1 模块的名称变成了 sub_package.sub_module1
# 上面的 from 导入语句中的 . 则表示的是这个模块名称中上一个 . 前面的路径 sub_package
# 相当于是 from sub_package import sub_module2
# module1.py 到 sub_package 目录中导入 sub_module2模块,这个当然没问题
问题点
如果直接修改成上述代码,那么执行module1.py
文件不会报错了,但是直接执行sub_module1.py
文件会报错
sub_module1.py
文件代码
from . import sub_module2
print(sub_module2.s2_m1)
print(sub_module2.s2_m2)
直接执行执行sub_module1.py
文件会报错
Traceback (most recent call last):
File "E:\StudyCode\Python\15-包和模块\包内导入\sub_package\sub_module1.py", line 2, in <module>
from . import sub_module2
ImportError: attempted relative import with no known parent package
# 导入错误:尝试相对导入,没有已知的顶级包
报错原因
sub_module1.py
文件,就是直接由Python解释器运行当前模块时,此时当前模块的名称__name__
则是main
from . import xxx
中的.
是获取模块名称中.
前面的路径,但是此时模块名称是main
并没有.
,所以会报错如果即想直接执行模块,又想其他模块导入都不报错,那么可以将模块代码修改成如下:
# 根据模块名称的情况,分别使用不同的导入方式
if __name__ == '__main__':
import sub_module2
else:
from . import sub_module2
print(sub_module2.s2_m1)
print(sub_module2.s2_m2)