引用资料:b站视频
【点击目录快速定位】
- 一、相关概念
- 1.1、模块
- 1.2、包/库
- 1.3、框架
- 二、包/模块的分类
- 2.1、标准包/模块
- 2.2、三方包/模块
- 2.3、自定义包/模块
- 三、包/模块的一般操作
- 3.1、创建模块
- 3.2、创建包
- 3.3、包/模块的基本信息
- 3.4导入包/模块
- 3.4.1、常规导入
- 3.4.2、from语句导入
- 3.4.3、what happen when importing module?
- 3.4.4、导入模块时的搜索路径
- 3.4.5、导入模块的一些场景
一个.py文件,记录一组相关的功能,供其他py文件import使用。
1.2、包/库把功能相关的模块和一个init.py放到一个文件夹里
1.3、框架比较“好”的包/库,用框架就能写出质量好的项目。如Web开发使用的框架有Flask、Django…
二、包/模块的分类python之所以强大,就是有很多库。
2.1、标准包/模块安装python时自带的,满足基本需求,所有安装了python的电脑都能用这些模块。
1.需要import os、time…
2.不需要import builtins print()、list()、int()…
# python3
import builtins
builtins.print("Hello world.")
print("Hello world.") # 这两种写法都一样
# python2
import __builtin__
2.2、三方包/模块
别人写好的,需要下载。
2.3、自定义包/模块自己写的。
三、包/模块的一般操作 3.1、创建模块直接创建一个.py文件
3.2、创建包新建一个文件夹,文件夹内创建__init__.py文件。(python2必须有、python3.3之后可以没有,但建议加上)
当import包之后,会先运行__init__.py文件。
3.3、包/模块的基本信息包/模块的存放位置:print(xx.__file__)
查看包/模块里的内容:print(dir(xx))
3.4导入包/模块 3.4.1、常规导入import M:导入单个模块,当M是某个包X里的模块时,应该写成 import X.M
import M1,M2导入多个模块
import M as 别名
引入别名除了能简化资源访问的前缀,还能增加程序的扩展性:
# 伪代码
if file_extension == "txt"
import txt_p
txt_p.open()
txt_p.read()
rxt_p.close()
elif file_extension =="doc"
import doc_p
doc_p.open()
doc_p.read()
doc_p.close()
————>
if file_extension == "txt"
import txt_p as p
elif file_extension =="doc"
import doc_p as p
p.open()
p.read()
p.close()
直接导入包名时,是不会导入包内的所有模块的。例如
dir1 | -- __init__.py | -- mod_a.py | -- mod_b.py ----------demo.py--------------- import dir1 # 此时是无法直接调用 dir1.mod_a或dir1.mod_b的对象的。 ----------demo.py---------------
3.4.2、from语句导入解决方案:1、按路径显示调用模块:import 包.模块
2、在__init__.py文件中import想要的模块 from . import 包中的模块
3、用from语句。
from A import B [as C]
【注意】只能从包导入模块or从模块导入模块资源,不能从包导入模块资源,不能从大包看到子包的模块。
from X import Y.M (x)
from X.Y import M (√) 【保证import后面是极简的,没有’点语法’】
慎用——防止变量命名冲突
批量导入:from 模块 import *、from 包 import *
*指定什么内容由开发者通过__all__变量决定(若没有__all__,则指定为所有非下划线开头的资源),因此,使用者无需关心包/模块里哪些资源是有用的(有些模块资源只是辅助、中间变量等,并不是拿来直接用的),只要用就行了。
----------test.py---------- from mod_A import * # 此时*就是模块mod_A里的num_1和name --------------------------- ----------mod_A------------ num_1 = 10 name = "Stephen" tmp = 0 __all__ = ["num_1","name"] # 注意__all__是列表,里面的元素是字符串 --------------------------- # from 包 import * # 指定*的内容时,在包内的__init__.py文件里定义__all__指定模块即可3.4.3、what happen when importing module?
第一次导入时:
1、在所导的模块下的命名空间中执行所有代码;
2、创建一个module对象,并将模块内所有的顶级变量以属性的形式绑定到该对象上;
3、在import语句所处的命名空间引入第2步创建的module对象的变量名称。
第二次导入时:直接执行第3步。(1、2步创建的module对象放到sys.modules里了<详见3.4.4>)
----------test.py----------------- # (对象.属性)
import mod_a
# 1、在所导的模块下的命名空间中执行所有代码;
num1 = 99
mod_a.run() # 运行结果num1为1,而非99。
# 因为run的其实是mod_a.num1
# 2、创建一个module对象,并将模块内所有的顶级变量以属性的形式绑定到该对象上;
print(mod_a) #
print(id(mod_a)) # 1697804609600
print(type(mod_a)) #
print(mod_a.__dict__) # 显示模块mod_a所有属性(不包括nums3)
# nums3不是mod_a的顶级变量
# 3、在import语句所处的命名空间引入第2步创建的module对象的变量名称。
def f():
import mod_a
# 正常使用mod_a对象
#不能使用mod_a对象
----------test.py-----------------
----------mod_a.py-----------------
num1 = 1
num2 = 2
def run():
num3 = 3
print("run")
print(num1)
----------mod_a.py-----------------
3.4.4、导入模块时的搜索路径用reload()重新装载模块:
因为在主文件上import后模块会被记录下来,所以对原模块进行的更新不影响已运行过的主文件对模块的使用。python用reload方法来重新加载修改后的模块。
import mod_a # …… 对mod_a修改了 from importlib import reload reload(mod_a)了解即可。现在的 IDE 大都不需要我们这么做。
当我们import 模块 时,python按照什么顺序搜索所需的模块呢?
第一次导入:
(1) 先找内置的模块(built-in),再找sys.path里的路径的模块
(2) sys.path:(包括四部分)
①当前目录下搜索
②环境变量PYTHONPATH中指定的路径列表
③特定路径下的.pth文件中指定的路径列表
④在python安装路径的lib库中搜索
用print(sys.path)可以查看其包含的路径
<打印出来的是一个列表,因此是有序的,python在搜索模块时就是按照这个顺序搜索的>
(3) 如果想要import的模块不在sys.path里面,可以追加进去,就能import了。
追加路径的方式:(详情观看视频)
第二次导入:
从已加载过的模块去找
可以用sys.modules查看已加载过的模块
3.4.5、导入模块的一些场景综上:导入一个模块时,python底层的搜索顺序为sys.modules——>built-in——>sys.path
①局部导入
# 当只需要在func里用到Module_1的一部分资源时,
# 在内部import更好,可以节省时间。(物尽其用)
# 毕竟func函数也不一定被调用到。
def func():
import Module_1
# 这里使用Module_1的资源
# 若出了func函数的命名空间,
# 就无法使用Module_1的资源。
②覆盖导入
1)自定义模块和非内置模块重名:按sys.path路径,优先级高的覆盖低的。
2)自定义模块和内置模块重名:内置模块覆盖自定义模块。
(ps.用from语句指明绝对路径就能使用这里的自定义模块)
from 包名 import 模块
ps.应避免重名!
③循环导入
---------test.py--------------- t1 = 't1' t2 = 't2' import other print(other.o1) print(other.o2) ---------test.py---------------
---------other.py-------------- o1 = 'o1' o2 = 'o2' import test print(test.t1) print(test.t2) ---------other.py--------------
通过3.4.3和3.4.4可以知道,两个文件互相导入,但不会像递归一样死循环,因为import的模块对象只创建一遍,不会再去执行第二遍。
④可选导入
# 优先导入other_1,如果other_1不存在
# 则导入other_2
try:
import other_1 as o
except ModuleNotFoundError:
import other_2 as o
# 【注意】1.两个模块都要起一个一样的别名,道理很简单。
# 2.两个模块应该除实现逻辑外,其他属性名、方法名
# 都相同,否则调用时候就出错了。
⑤包内导入
包内导入的方式:
绝对导入:指定包名和模块名。from 包名 import 模块名
相对导入:from . import 模块名 和 from .. import 模块名
如果一个py文件以脚本的形式执行python file,它的名称就是__main__ (print(__name__))
如果一个py文件是被以模块的形式加载的,它的名称由加载路径决定,一般是:包名.子包名.模块名
比如package_2.package_1.module_A,此时package_2叫做【顶级名称】
【注意】对python2而言,包内导入时,import 模块 属于隐式相对导入,即和from . import 模块 作用是一样的,若想和python3一样是绝对导入,需在前面加上from __future__ import absolute_import。
总结:
包内导入:使用相对导入
包外导入:使用绝对导入



