Python_base20181122_包,模块

什么是包?
包本质上就是一个文件夹,只不过包比普通的文件夹多了一个__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的目录。

猜你喜欢

转载自blog.csdn.net/weixin_41687289/article/details/84342506