循环导入问题、文件类型判断、模块的查找顺序、绝对导入与相对导入、软件开发目录规范
今日学习内容总结
在昨日的学习中,我们学习了生成器及其表达式。并且对模块以及模块的导入进行一定的了解。而今天我们还是针对模块进行学习。在学习过程中,要记住我们的项目中的文件名肯定都是以英文为主。尽量不要使用中文,尽量做到见名知意。
循环导入问题
循环导入就是两个文件彼此导入彼此。而两个模块直接相互导入,且相互使用其名称空间中的名字,但是有些名字没有产生就使用,就出现了循环导入问题。循环导入的时候极有可能出现某个名字还没有被创建就使用的情况导致报错:
# 模块teset
import test1
def a():
test1.d()
a()
# 模块 test1
import teset
def d():
teset.a()
d()
# 这个时候运行会报错 module 'test1' has no attribute 'd'
在以后的编程里,要尽量去避免出现循环导入的问题。但是如果确实需要循环导入,那么需要确保双方使用的名字都必须提前定义好。解决方法1:将导入模块的句式写在定义名字的下面。解决方法2:将导入模块的句式写在函数体代码内。
判断文件类型
py文件可以被分为两种类型:1.执行文件。2.被导入文件。
有一个内置变量__name__,当__name__所在的文件是执行文件的时候 结果是__main__。当__name__所在的文件是被导入文件时候 结果是文件名。代码示例:
# 执行文件
print(__name__) # __main__
# 被导入文件 test1
print(__name__) # test1
name 是属于 python 中的内置类属性,就是它会天生就存在与一个 python 程序中,代表对应程序名称。因此在被导入文件可以使用这个方法,设置判断是执行文件才执行的代码:
# pycharm中快捷方式:main+tab键
if __name__ == '__main__':
模块的查找顺序
模块的查找顺序:从内存空间中查找 > 从内置模块中查找 > 去sys.path查找(类似于我们前面学习的环境变量)。如果在这三个地方都没找到,会直接报错。
验证先从内存空间找
import test1
import time
time.sleep(15) # 睡眠期间将md1文件删除
print(test1.name) # jason
# 在操作过程中,我们首先执行这个文件。然后删除,在硬盘内就会从占有态变成自由态。而在内存里面还在,因为我们已经执行了这个文件。所以最终还是能打印出结果。这也是先从内存空间查找的证明。
验证再从内置模块中查找
import time
print(time)
print(time.time())
执行结果:
<module 'time' (built-in)>
1648215037.89744
# 在创建py文件时候一定不要跟模块名(内置、第三方)冲突。
验证sys.path(类似于我们前面学习的环境变量)
import sys
print(sys.path) # 下面的注释内就是打印结果
'''
['C:\\Users\\Administrator\\Desktop\\Typora\\day15\\day15', 'C:\\Users\\Administrator\\Desktop\\Typora\\day15\\day15', 'D:\\PyCharm 2020\\plugins\\python\\helpers\\pycharm_display', 'D:\\Python36\\python36.zip', 'D:\\Python36\\DLLs', 'D:\\Python36\\lib', 'D:\\Python36', 'D:\\Python36\\lib\\site-packages', 'D:\\PyCharm 2020\\plugins\\python\\helpers\\pycharm_matplotlib_backend']
'''
# 我们发现结果是一个列表,里面存放了很多路径。其实sys.path中虽然有很多路径,但是只需要重点关注第一个。第一个其实就是执行文件所在的路径。因为当内存中和内置中都没有要查找的模块时,就会去下面的路径中挨个查找。这也是说为什么类似于之前学习的环境变量。
当使用上面三种方法都没有找到你要找的模块,那么这里有两种解决方法。
解决方法1:
import sys
#因为sys.path是一个列表所以我们可以使用append方法进行追加
sys.path.append(r'D:\pythonproject\test\AAA')
import a
a.f1()
# pycharm会自动将项目目录所在的路径添加到sys.path中
解决方法2:
# 利用from...import...句式指名道姓的查找
from a import name 从文件夹a中导入name模块
from a.b import c 从a文件夹中的子文件b中导入模块c
绝对导入与相对导入
在导入模块的时候一切查找模块的句式都是以执行文件为准。无论导入的句式是在执行文件中还是在被导入文件中。
绝对导入
永远按照执行文件所在的路径一层层往下查找(无脑查找即可)。在python的执行文件或模块中,使用类似import 模块名、import 包名.模块名 、from 包名.模块名 import 内容等导入语法时,就是在用绝对路径导入模块。
相对导入
相当导入打破了必须参照执行文件的所在路径的要求 只需要考虑当前模块所在的路径然后使用特殊符号.去查找其他模块即可。使用相对导入,就不需要考虑执行文件到底是谁了,只需要知道模块与模块之间的相对位置。如:
from . import test1 # 导入当前目录下的test1
from .. import test1 # 导入上一级目录下的test1
'''
.表示当前路径
..表示上一层路径
../..表示上上一层路径
'''
以后如果想一劳永逸,那么就只使用绝对导入即可。因为绝对路径不需要动脑子。
包
包,就是内部含有__init__.py的文件夹,也是模块的另一种形式。在pycharm中甚至直接提供了创建包的选项(python package)。
导入包,其实就是向包里面的__init__.py索要名字。1.如果想直接通过包的名字使用包里面所有的模块 那么需要在__init__.py中提前导入。好处在于__init__可以提前帮你准备好可以使用的名字。2.也可以直接忽略__init__的存在使用绝对导入即可。好处在于不需要考虑包的存在,直接当成普通文件夹即可。
编程思想演变
1.小白阶段,此阶段写代码就是在一个文件内不停地堆叠代码的行数(面条版本)
2.函数阶段,此阶段写代码我们学会了将一些特定功能的代码封装到函数中供后续反复调用
3.模块阶段,此阶段不单单是将功能代码封装成函数,并且将相似的代码功能拆分到不同的py文件中便于后续的管理
软件开发目录规范
1.bin文件夹
存放程序的启动文件 start.py
2.conf文件夹
存放程序的配置文件 settings.pyy
3.core文件夹
存放程序的核心业务 src.py 就是最为重要的代码 能够实现具体需求
4.lib文件夹
存放程序公共的功能 common.py
5.db文件夹
存放程序的数据 userinfo.txt
6.log文件夹
存放程序的日志记录 log.log
7.readme文本文件
存放程序的说明、广告等额外的信息
8.requirements.txt文本文件
存放程序需要使用的第三方模块及对应的版本
目录的名字可以不一致,但是主要的思想是一致的。就是为了便于管理。拿到启动文件之后直接运行即可,需考虑程序内部的复杂程度。

学习内容总结
浙公网安备 33010602011771号