1、模块的导入
- 模块:已经写好的一组功能的集合
- 模块的类型
- py文件
- dll文件(c语言)
- zip文件
(1)自己写模块文件
- 命名要规范(符合变量名要求),不要和已存在的模块重名
(2)import
-
导入模块时要注意路径
-
导入一个模块就是执行该模块的代码,流程如下
找到模块 --> 判断该模块是否已经被导入过(sys.modules) --> 如果未被导入过 --> 创建一个属于这个模块的命名空间 --> 如果给模块起别名 --> 则让该别名指向这个命名空间(这样就不能使用模块名了) --> 如果没有起别名 --> 则让模块名指向这个空间 --> 执行模块中的代码
- 可以使用模块中的任何变量,假设我们导入模块myModule(里面有变量
name
和函数sum()
)print(myModule.name) # 调用模块中的变量
myModule.sum(1,2) # 调用模块中的函数
- 可以使用模块中的任何变量,假设我们导入模块myModule(里面有变量
-
命名空间:模块和当前文件在不同的命名空间中
-
为模块起别名:
import <模块名> as <模块别名>
-
一行导入多个模块:
import os [as o], sys [as s]
-
导入模块时的建议:先导入内置模块,再导入第三方模块,最后导入自定义模块
(3)from import
-
即导入模块中的具体变量
-
导入流程
- 和import一样,只是在找到要导入的变量后,创建一个引用指向该变量
- 模块被多次导入的话,只执行模块代码一次
-
命名空间:重名情况下,当前命名空间会覆盖模块引用
-
为模块起别名:
from module import func1 as f1
-
一行导入多个模块:
from module import func1, func2
-
*
和__all__
的关系-
from module import *
表示导入模块所有变量 -
__all__
在模块中定义,能够约束*
的导入变量个数 -
例子:
# myModule.py __all__ = ["name1"] name1 = 'aaa' name2 = 'bbb' # test.py from myModule import * print(name1) --> no error print(name2) --> error:name2 is not defined!
-
(4)import和from import的区别
-
import
当前命名空间 模块命名空间 name1 module.name1 name2 module.name2
-
from import
假设导入了name1,name2 当前命名空间 模块命名空间 name1 ---------指向---------> name1 name2 ---------指向---------> name2
(5)模块中引用
- 模块的循环引用:模块之间不允许循环引用(即模块之间互相导入)
- 模块的加载与修改:在导入后修改模块,修改不会立即生效,必须要reload才能生效
- 把模块当成脚本执行
- 脚本和模块
- 当我们直接执行py文件时,即是以脚本的模式执行文件
- 而当我们导入一个模块时,也会执行导入模块里的代码
- 但是我们执行脚本(希望和用户交互)和导入模块(不希望有任何输出,除非我们调用里面的功能)是不同的
- py文件的
__name__
- 当文件被当作模块导入时,
__name__ == "模块名字"
- 当文件被当作脚本执行时,
__name__ == "__main__"
- 在py文件中,把当作脚本时要执行的代码写在
if __name__ == "__main__":
后面,这样,一个py文件即可以当作脚本,也可以当作模块使用
- 当文件被当作模块导入时,
- 脚本和模块
- 模块的搜索路径:
sys.path
,修改这个列表可以更改模块的搜索路径
2、包
- 什么是包
- 包就是有一个
__init__.py
文件的文件夹 - 包是几个模块的集合
- 包就是有一个
- 导入包中的模块
- import和from import
- 注意:凡是在导入中带
.
的左边必须是包,from import的import必须导入准确的模块,不能带.
- 导入包
- 导入一个包,不意味着这个包里的所有内容都是可以被执行的
sys.path
= 当前执行脚本所在目录- 如果一个包里有另一个包,直接导入包时要注意路径
- 导入一个包的过程:
- 导入一个包,相当于执行了该包的
__init__.py
- 可以在
__init__.py
中导入模块,这样直接导入包时就把包中的模块导入了 - 所以直接导入包时,需要通过设计
__init__.py
文件,来完成导入包后的操作
- 导入一个包,相当于执行了该包的
- 绝对导入:
- 直接使用绝对路径导入
- 相对导入:
.
表示当前目录,..
表示上一级目录- 含有相对导入的文件不能被直接执行
- 例子见文件夹“包的导入”
3、项目规范
project---bin---__init__.py
| |---start.py
|
|---conf---__init__.py
|
|---core---__init__.py
| |---xxx.py
|
|---db---__init__.py
|
|---lib---__init__.py
|
|---xxx.py
- bin:启动脚本
- conf:配置文件
- core:核心代码和模块
- db:数据库
- lib:既不是内置模块/也不是第三方模块,是一个通用模块
4、例子
# 文件结构
dream:包的导入 dream$ tree .
.
├── package
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── __init__.cpython-36.pyc
│ │ ├── module1.cpython-36.pyc
│ │ └── module2.cpython-36.pyc
│ ├── module1.py
│ └── module2.py
└── test.py
2 directories, 7 files
# 测试代码内容
dream:包的导入 dream$ cat test.py
#!/anaconda3/bin/python3
import package
print("this is test.py")
package.module1.m1_func()
package.module2.m2_func()
# 包的__init__.py的内容
dream:包的导入 dream$ cat ./package/__init__.py
#!/anaconda3/bin/python3
print("package is importing...")
from . import module1
from . import module2
print("package has been imported!")
# 包的两个模块的内容
dream:包的导入 dream$ cat ./package/module1.py
#!/anaconda3/bin/python3
def m1_func():
print("this is module1!")
dream:包的导入 dream$ cat ./package/module2.py
#!/anaconda3/bin/python3
def m2_func():
print("this is module2!")
# 执行结果(test.py)
dream:包的导入 dream$ python test.py
package is importing...
package has been imported!
this is test.py
this is module1!
this is module2!