Python包,模块,库
模块module
module的定义
- 模块就是Python文件,里面定义了很多的函数、类、变量等。
- 一个完整大型的python程序是由模块和包的形式组织起来的。
module的作用
- 模块让你能够有逻辑地组织你的 Python 代码段。
- 把相关的代码分配到一个模块里能让你的代码更好用,更易懂。
- 模块能定义函数,类和变量,模块里也能包含可执行的代码。
- 可以避免函数名和变量名冲突,相同名字的变量,函数等完全可以分别存在不同的模块中。
- 使用了系统和第三方的module,拿来主义。
模块的分类
通常把python中的标准模块和第三方模块成为库,库只是一个理解上的概念,强调其功能性。在Python中,具有某些功能的模块和包都可以被称作库。模块有诸多函数组成,包由诸多模块机构化组成,库中也可以包含包、模块和函数。
- 标准模块(库),python解释器自带。
- 第三方模块(库),需要通过install安装。
- 自定义模块
模块的使用
- 模块在使用之前需要先进行import。
import语句
- 分行写的方式更加清晰,推荐。
- 在使用模块内部的变量等需要加上模块名.。
- 在一个py文件中可能会包含多种模块,内置模块、第三方模块、自定义模块。为了增加代码可读性以及更好的符合PEP8规范(python开发中编写代码的规范)通常在文件开头导入模块,并且将三种不同模块中间用空行隔开。
# 格式1: 逗号隔开
import module1[, module2[,... moduleN]
# 格式2: 分行写
import module1
import module2
...
from…import 语句
- 使用时无需再加模块名前缀。
from modname import name1[, name2[, ... nameN]]
优缺点 | import 模块名 | from 模块名 import 名字 |
---|---|---|
优点 | 肯定不会与当前名称空间的名字冲突 | 不加前缀,代码更精简 |
缺点 | 加前缀显得代码不简洁 | 容易与当前名称空间的名字混淆,IDE下模块下的attribute不好提示 |
from…import* 语句
- 把一个模块的所有内容全都导入到当前的命名空间。
- 占用过多的内存,不应过多使用。
import…as …
- 当被导入的模块名字过长时就可以使用起别名的方式来精简代码。
- 别名可以很好地避免与当前文件的命名空间中的名字发生冲突。
import modname as 变量名
import语句举例
from random import randint
import time
import math as mt
from numpy import *
print(randint(1,5))
print(time.time())
print(mt.sqrt(9))
print(list(arange(0.1,1)))
result:
1
1651757322.7786858
3.0
[0.1]
包package
包的定义
- 体现了模块的结构化管理思想,包由模块文件构成,将众多具有相关功能的模块文件结构化组合形成包。
- 简单来说,包就是文件夹,但该文件夹下必须存在 init.py 文件, 该文件的内容可以为空。init.py 用于标识当前文件夹是一个包。
- 包结构使得处于不同包下的相同模块名的文件不再冲突。
- 模块和包名要尽量和内置的模块名不相同,不然会覆盖内置的模块
包组织结构图
包中模块的导入
- 在导入包中内容时,首先会执行包中的__init__.py文件。
from import
from package_name import module_name
from package_name.module_name import *
from package_name.module_name import name1, name1...
from package_name import module_name as name
绝对路径导入
- 基于项目来写全路径,package.subpakage.moudule。
- 推荐使用。
└── project1
| ├── package_A
| │ ├── __init__.py
| │ ├── module_A.py
| │ └── module_B.py
| │ └── CurrentProgram.py
| └── package_B
| ├── __init__.py
| ├── module_C.py
| ├── module_D.py
| └── subpackage_B
| └── module_E.py
例如在module_B中导入module_E,方法为 from package_B.subpackage_B import module_E
相对路径导入
- 在文件中导入同级别module(在同一目录下),可以用.模块名导入。
- 当前module(name=main)导入同级module不可使用相对路径,因为相对路径导入依赖文件__name__,如果为当前执行文件,name=main,这样__package__会被设为None,而相对引用依赖__package__的值,就找不到相对引用的位置了。
└── project1
| ├── package_A
| │ ├── __init__.py
| │ ├── module_A.py
| │ └── module_B.py
| │ └── CurrentProgram.py
module_B中导入module_A中的test方法, from module_A import test
init.py文件
- Python中package的标识,不能删除。
- 定义__all__用来控制*方式的导入。
- 当导入包时,首先会执行__init__这个module。
- 可以放一些初始化代码(不建议在__init__中写python模块,可以在包中在创建另外的模块来写,尽量保证__init__.py简单)
__all__限制导入
- 如果想通过from 包import *把包中所有的模块都导入进行使用的话,需要在__init__中加上__all__=[模块名],否则一个模块都不执行。
- 而如果是普通的from 模块import *,那么__all__=[]没有的话,则所有的导入,有的话,只有[]中暴露出来。
- 只有在带*的导入方式中才起作用,其它导入方式不受__all__的影响。
# example.py中的内容
__all__ = ["a"]
a = 1
b = 2
# 导入的语句内容
from simple import *
print(a)
print(b)
result:
NameError: name 'b' is not defined
循环导入
循环导入定义
- 循环导入的问题指的是在一个模块加载/导入的过程中导入另外一个模块,而另一个模块中又返回来导入第一个模块中的名字,由于第一个模块尚未加载完毕,所以引用失败,抛出异常。
循环导入举例
"""
1. 当modules模块执行test.work import w1想要导入时,跑到work.py中,却看到from test.modules import m1, 而modules目前还没有m1,必须把第一行test.work import w1执行完毕后才能到定义m1的语句m1 = "modules1",所以会发生错误。
2. 同理对work模块也
3. 一样。
"""
modules.py内容
from test.work import w1
m1 = "modules1"
print("-----------打印work中的w1----------", w1)
work.py内容
from test.modules import m1
w1 = "work"
print("-----------打印modules中的m1----------", m1)
result:报错
循环导入解决方案
import语句放在使用的变量或函数之前
modules.py内容
m1 = "modules1"
from test.work import w1
print("-----------打印work中的w1----------", w1)
work.py内容
w1 = "work"
from test.modules import m1
print("-----------打印modules中的m1----------", m1)
import语句放在函数之中
- 将import放在定义函数之中,这样在导入时不会执行,只有在函数调用时才会执行。
modules.py内容
m1 = "modules1"
def func_modules():
from test.work import w1
print("-----------打印work中的w1----------", w1)
work.py内容
w1 = "work"
def func_work():
from test.modules import m1
print("-----------打印modules中的m1----------", m1)