什么是包?
包本质上就是一个文件夹,只不过包比普通的文件夹多了一个__init__.py
文件。
什么是模块?
模块本质上就是一个py
文件。
为什么要引入包和模块?
引入函数是为了防止在同一个模块中多写重复代码。
引入模块是为了防止在同一个包中多写重复模块。
引入包是为了将模块分门别类的放好。
python中都有什么样的模块?
- python标准库
- 第三方模块
- 自定义模块
import
or from... import ...
的执行流程:
别管是import
还是 from...import...
都会把相关的模块(.py
文件)执行一遍。
可用的语法:
import 模块
from 模块 import 函数
import 包.模块
from 包 import 模块
from 包.模块 import 函数
__name__
的作用:
if __name__ == 'main':
# 俩作用。
如果调用者是它自己,则执行
如果它是被调用者,则不执行。
根据这个特性,可以当作测试代码。
也就是说,加了这个东西,如果包被调用的话,是不执行的。而且不影响你自己测试。
因为你自己测试的时候是可执行的。
当写好的py
文件被自己用时,__name__
的值是__main__
写好的py
文件被别人用时,__name__
的值是此py
文件的路径
注意:
调包的时候一定要注意,path
里只把调用者的路径加入了path
。操作系统只根据path
去找指定的模块或包。调包的时候是有优先级的,优先级最高的是time
,sys
等用C语言写成的内置在了python
编译器中的模块。然后再根据path
列表去找指定的模块或包。
包和模块的补充:
一般来说,我们的目录结构是这样的:
那么,a.py
想调用c.py
,怎么做?
根据之前的讨论,执行a.py
时,操作系统会将xxxxxxx/dir1
加入环境变量。但是环境变量中并没有dir2
这个目录,所以根本没办法通过from dir2 import c
这样来找。但是在pycharm
中这么写反而过了,为啥?
from dir2 import c # 在终端下这么写是不行的
# 在pycharm下这么写可以是因为pycharm把工程目录module_test加入到了sys.path
import sys
print(sys.path)
因为pycharm
自作主张的把工程目录加入到了sys.path
中,用终端执行一下就看出来了。
D:\pythonprogram\module_test\dir1>python a.py
['D:\\pythonprogram\\module_test\\dir1', 'C:\\Users\\bjfuvth\\AppData\\Local\\Programs\\Python\\Python37\\python37.zip', 'C:\\Users\\bjfuvth\\AppData\\Local\\Programs\\Python\\Python37\\DLLs', 'C:\\Users\\bjfuvth\\AppData\\Local\\Programs\\Python\\Python37\\lib', 'C:\\Users\\bjfuvth\\AppData\\Local\\Programs\\Python\\Python37', 'C:\\Users\\bjfuvth\\AppData\\Local\\Programs\\Python\\Python37\\lib\\site-packages']
终端下会提示找不到dir2
D:\pythonprogram\module_test\dir1>python a.py
Traceback (most recent call last):
File "a.py", line 1, in <module>
from dir2 import c
ModuleNotFoundError: No module named 'dir2'
另外pycharm
还干了个好事儿。如果你想输出__file__
.看名字是应该输出文件名,但是在pycharm
下你会拿到这个文件的绝对路径。
代码:
print(__file__)
pycharm
的输出:
D:/pythonprogram/module_test/dir1/a.py
终端的输出:
a.py
所以说在操作这块知识点的时候一定要注意pycharm
干的两件好事儿。
那么问题来了?我们怎么在刚刚所示的目录结构中,写出可移植性强的程序呢?如果对方装的不是pycharm
呢?那就需要我们自己干pycharm
干过的好事儿了。
import os
import sys
ABS = os.path.abspath(__file__) # 拿到file的绝对路径
print(ABS)
LASTABS = os.path.dirname(ABS)
print(LASTABS) # 这样拿到file的目录
LL = os.path.dirname(LASTABS) # 拿到file目录的父级目录
# file的目录是到dir1 它的父级是module_test 这个目录下就能找到dir2了
print(LL)
sys.path.append(LL) # 将module_test临时加入环境变量
print(sys.path)
from dir2 import c
这样在pycharm
下和终端下都可以执行了,可移植性贼好。
终端下运行结果:
D:\pythonprogram\module_test\dir1>python a.py
D:\pythonprogram\module_test\dir1\a.py
D:\pythonprogram\module_test\dir1
D:\pythonprogram\module_test
['D:\\pythonprogram\\module_test\\dir1', 'C:\\Users\\bjfuvth\\AppData\\Local\\Programs\\Python\\Python37\\python37.zip', 'C:\\Users\\bjfuvth\\AppData\\Local\\Programs\\Python\\Python37\\DLLs', 'C:\\Users\\bjfuvth\\AppData\\Local\\Programs\\Python\\Python37\\lib', 'C:\\Users\\bjfuvth\\AppData\\Local\\Programs\\Python\\Python37', 'C:\\Users\\bjfuvth\\AppData\\Local\\Programs\\Python\\Python37\\lib\\site-packages', 'D:\\pythonprogram\\module_test']
pycharm
下运行结果:
D:\pythonprogram\module_test\dir1\a.py
D:\pythonprogram\module_test\dir1
D:\pythonprogram\module_test
['D:\\pythonprogram\\module_test\\dir1', 'D:\\pythonprogram\\module_test', 'D:\\pythonprogram\\module_test\\venv\\Scripts\\python37.zip', 'C:\\Users\\bjfuvth\\AppData\\Local\\Programs\\Python\\Python37\\DLLs', 'C:\\Users\\bjfuvth\\AppData\\Local\\Programs\\Python\\Python37\\lib', 'C:\\Users\\bjfuvth\\AppData\\Local\\Programs\\Python\\Python37', 'D:\\pythonprogram\\module_test\\venv', 'D:\\pythonprogram\\module_test\\venv\\lib\\site-packages', 'D:\\pythonprogram\\module_test\\venv\\lib\\site-packages\\setuptools-39.1.0-py3.7.egg', 'D:\\pythonprogram\\module_test\\venv\\lib\\site-packages\\pip-10.0.1-py3.7.egg', 'D:\\Users\\bjfuvth\\AppData\\Roaming\\JetBrains\\PyCharm 2018.2.2\\helpers\\pycharm_matplotlib_backend', 'D:\\pythonprogram\\module_test']
补充一点,os.path.dirname()
不光可以获取文件的目录,还能获取目录的目录。
什么叫目录? 比如D:\pythonprogram\module_test\dir1\a.py
。。
D:\pythonprogram\module_test\dir1
就是 a.py
的目录。