不走心的努力,都是在敷衍自己
——24.3.19
万字长文,讲解异常、模块、包,看这一篇就足够啦
什么是异常?
当检测到一个错误时,python解释器就无法继续执行了,反而出现了一些错误的提示,这就是所谓的异常,也就是我们所说的BUG
什么是BUG?
bug就是指异常的意思,因为历史因为小虫子导致计算机失灵的案例,所以延续至今,bug就代表软件出现错误
异常≈BUG
一、异常的捕获方法
1.为什么要捕获异常
当我们的程序遇到了BUG,那么接下来有两种情况
①整个程序因为一个BUG停止运行
②对BUG进行提醒,整个程序继续进行
捕获异常的作用在于:提前假设某处会出现异常,做好提前准备,当真的出现异常的时候,可以有后续手段
2.捕获常规异常
①基本语法:
try:
可能发生错误的代码
except:
如果出现异常执行的代码
②快速入门:
需求: 尝试以"r"模式打开文件,如果文件不存在,则以"w"方式打开
r方式读取文件,w写入文件,如果文件不存在,w方式创建文件
try:
f = open("一切都会好的.txt",'r')
except:
f = open("一切都会好的.txt",'w')
# 基本捕获语法
try:
f = open('E:/abcdePython.txt',"r",encoding="UTF-8")
except:
print("出现了异常,文件不存在,将打开文件的方式改为w模式")
f = open('E:/abcdePython.txt',"w",encoding="UTF-8")
程序将不会报错,程序将会正常运行
3.捕获指定异常
基本语法:
try:
print(name)
except 异常类型 as e:
print('name变量名称未定义错误')
注意事项:
①如果尝试执行的代码的异常类型和要捕获的异常类型不一致,则无法捕获异常
②一般try下方只放一行尝试执行的代码
③异常类型是已知的,只进行捕获指定了的异常类型,其他类型的异常不去理会
# 捕获指定的异常
try:
print(name)
except NameError as e:
print('name变量名称未定义错误')
print(e)
name这个变量并没有被定义
4.捕获多个异常
当捕获多个异常时,可以把要捕获的异常类型的名字,放到except后,并使用元组的方式进行书写
try:
print(1/0)
except(NameError,ZeroDivisionError):
print('ZeroDivision错误')
# 捕获多个异常
try:
print(1/0)
except(NameError,ZeroDivisionError) as e:
print('ZeroDivision错误')
5.捕获所有异常(顶级方式)
捕获所有的异常,与基础写法作用相同,都可以捕获出所有的异常
Exception是顶级的异常,其余的异常都是基于Exception得来的
①
try:
异常代码
except:
处理措施
②
try:
异常代码
except Exception as e:
处理措施
# 捕获所有异常
try:
1/0
except Exception as e:
print("出现了异常")
6.异常else
else表示的是如果没有异常执行的代码,else是一个可选项,可以写也可以不用写
try:
print(1)
except Exception as e:
print(e)
else:
print("我是else,是没有出现异常时执行的代码")
try:
1/2
except Exception as e:
print("出现了异常")
else:
print("没有出现异常")
7.异常的finally
finally表示的是无论是否异常都要执行的代码,例如关闭文件
try:
f = open('test,txt','r')
except Exception as e:
f = open('test.txt','w')
else:
print('没有异常,真好')
finally:
f.close()
# 异常的finally
try:
f = open("E:/12345.txt",'r',encoding="UTF-8")
except Exception as e:
print("出现了异常")
f = open("E:/12345.txt",'w',encoding="UTF-8")
else:
print("没有异常")
finally:
print("我是finally,有没有异常我都要执行")
f.close()
第一次运行: (没有文件)
第二次运行:(在第一次运行时已经被创建出文件了)
try和except是必要元素,而else和finally是可选的元素,例如关闭文件就是必要元素
总结
1.为什么要捕获异常?
在可能发生异常的地方,进行捕获,当异常出现的时候,提供解决方式,而不是任由其导致程序无法执行
2.捕获异常的语法?
as e给异常起别名
try:
可能要发生异常的语句
except[异常 as 别名:]
出现异常时应做的事情
[else:]
未出现异常时应做的事情
[finally:]
不管出不出现异常都会做的事情
3.如何捕获所有异常?
异常的种类多种多样,如果想要捕捉任何类型的异常,那么使用:
①except:
②except Exception:
两种方式捕获全部异常,第二种方式使用较多,一般情况下使用第二种方式
二、异常的传递
异常的传递
异常是具有传递性的
当函数func01中发生异常,并且没有捕获处理这个异常的时候,异常会传递到函数func02,当func02也没有捕获处理这个异常的时候,main函数会捕获这个异常,这就是异常的传递性
提示
当所有函数都没有捕获异常的时候,程序就会报错
# 定义一个出现异常的方法
def func1():
print("func1 开始执行")
num = 1/0
print("func1 结束执行")
# 定义一个无异常的方法,调用上面的方法
def func2():
print("func2 开始执行")
func1()
print("func2 结束执行")
# 定义一个main函数,调用上面的方法
def main():
print("main函数开始执行")
try:
func2()
except Exception as e:
print(f"出现了异常,异常的信息是:{e}")
# 调用了一下main方法
# 异常通过方法的调用层层传递
main()
函数调用中的异常可以直接在最高层报错
三、python模块
1.什么是模块?
python模块是一个python文件,以.py结尾,模块能定义函数,类和变量,模块里也能包含可执行文件
2.模块的作用?
python中有很多不同的模块,每一个模块可以帮助我们们快速实现一些功能,比如实现和时间相关的功能就可以使用time模块,我们可以认为一个模块就是一个工具包,每一个工具包中都有各种不同的工具供我们使用进而实现各种不同的功能
3.模块的导入方式
模块在使用前需要先导入,导入的语法如下:
[from 模块名] import [模块 | 类 | 变量 | 函数 | *] [as 别名]
常用的组合形式如:
import 模块名
from 模块名 import 类、变量、方法等
from 模块名 import *
import 模块名 as 别名
from 模块名 import 功能名 as 别名
①import模块名
基本语法:
import 模块名
import 模块名1,模块名2
模块名.功能名()
案例:导入time模块
# 导入时间模块
import time
print("开始")
# 让程序睡眠疫苗(阻塞)
time.sleep(1) # 只导入模块名,调用具体的方法时,应该调用模块名.方法名
print("结束")
# 使用import导入time模块使用sleep功能(函数)
import time # 导入python内置的time模块(time.py这个代码文件)
print("一切都会好的")
time.sleep(9) # 通过.就可以使用模块内部的全部功能(类、函数、变量)
print("我一直相信")
②from 模块名 import 功能名
基本语法:
from 模块名 import 功能名
功能名()
案例:导入time模块中的sleep方法
# 导入时间模块中的sleep方法
from time import sleep
print("开始")
# 让程序睡眠1秒(阻塞)
sleep(1)
print("结束")
说明只导入某个模块内的某个方法,不导入其他方法,所以使用不了其他方法
# 使用from导入time的sleep功能(函数)
# 导入时间模块中的sleep方法
from time import sleep
print("开始")
# 让程序睡眠1秒(阻塞)
sleep(1)
print("结束")
③from 模块名 import *
基本语法:
from 模块名 import *
功能名()
案例:导入time模块中所有的方法
# 导入时间模块中所有的方法
from time import *
print("开始")
# 让程序睡眠1秒(阻塞)
sleep(1)
print("结束")
# 使用 * 导入time模块的全部功能
# 导入时间模块中所有的方法
from time import *
print("开始")
# 让程序睡眠1秒(阻塞)
sleep(1)
print("结束")
④使用as给特定功能加上别名
基本语法:
# 模块定义别名
import 模块名 as 别名
# 功能定义别名
from 模块名 import 功能 as 别名
案例:
# 模块别名
import time as tt
tt.sleep(2)
print("hello")
# 功能别名
from time import sleep as sl
sl(2)
print("hello")
as别名可以在其他三种方式中加入定义别名
# 使用as给特定功能加上别名
import time as t
print("一切都会好的")
t.sleep(6)
print("我一直相信")
# 使用as导入模块的某特定功能加上别名
from time import sleep as ft
print("一切都会好的")
ft(3)
print("未来可期")
4.总结
什么是模块?
模块就是一个python代码文件,内涵类、函数、变量等,我们可以导入进行使用
如何导入模块?
[from 模块名] import [模块 | 类 | 变量 | 函数 | * ] [as 别名]
注意事项:
①from可以省略,直接import即可
②as别名可以省略
③通过“.”来确定层级关系
④模块的导入一般写在代码文件的开头位置
⑤按住crtl键再点击导入的包/功能名,就可以直接查看源文件代码
eg:from time import sleep
# 演示python的模块导入
# 使用import导入time模块使用sleep功能(函数)
import time # 导入python内置的time模块(time.py这个代码文件)
print("一切都会好的")
time.sleep(9) # 通过.就可以使用模块内部的全部功能(类、函数、变量)
print("我一直相信")
# 使用from导入time的sleep功能(函数)
# 导入时间模块中的sleep方法
from time import sleep
print("开始")
# 让程序睡眠1秒(阻塞)
sleep(1)
print("结束")
# 使用 * 导入time模块的全部功能
# 导入时间模块中所有的方法
from time import *
print("开始")
# 让程序睡眠1秒(阻塞)
sleep(1)
print("结束")
# 使用as给特定功能加上别名
import time as t
print("一切都会好的")
t.sleep(6)
print("我一直相信")
# 使用as导入模块的某特定功能加上别名
from time import sleep as ft
print("一切都会好的")
ft(3)
print("未来可期")
5.自定义模块
制作自定义模块
python中已经帮我们实现了很多的模块,不过有时候我们需要一些个性化的模块,这里就可以通过自定义模块实现,也就是自己制作一个模块,正常创建一个python文件并正常写代码,需要使用的时候就import它,或者from它import去调用某个功能
案例:新建一个python文件,命名为my_modulel.py,并定义test函数
注意:
每个Python文件都可以作为一个模块,模块的名字就是文件的名字,自定义模块名必须要符合标识符命名规则
# 演示自定义模块
# 导入自定义模块使用方法1:
import My_Module1
My_Module1.testA(11,4)
My_Module1.testB(11,4)
My_Module1.testC(11,4)
My_Module1.testD(11,4)
# 导入自定义模块方法2:
from My_Module1 import testA
testA(6,27)
# 导入不同模块的同名功能
from My_Module1 import testA
from My_Module2 import testA # 发亮表示被使用了
testA(11,4)
# My_Module1模块:
def testA(a,b):
print(a + b)
if __name__ == '__main__':
# __name__为自动标记变量,通过这个功能可以调用函数又不用随意都调用
testA(1,2)
def testB(a,b):
print(a - b)
def testC(a,b):
print(a * b)
def testD(a,b):
print(a / b)
# My_Module2模块:
def testA(a,b):
print(a % b)
注意事项:
当导入多个模块的时候,且模块内有同名功能,当调用这个同名功能的时候,调用到的是后面导入的模块的功能
当导入多个模块的同名功能时,在pycharm中,发灰表示没有被使用,发亮表示被进行调用
测试模块 __main__变量
在实际开发中,当一个开发人员编写完一个模块后,一般会在py文件中添加一些测试信息和测试代码
此时无论是当前模块还是调用了该模块的文件,在运行的时候都会执行这些测试代码
解决方案:
if __name__=='__main__':
测试代码
在添加这段代码后,main变量下的函数只会在函数内部被执行,在调用这个模块和函数时,不会被执行
def testA(a,b):
print(a + b)
if __name__ == '__main__':
# __name__为自动标记变量,通过这个功能可以调用函数又不用随意都调用
testA(1,2)
__all__变量
如果一个模块文件中有“__all__”变量,当使用‘from xxx import *‘导入时,只能导入这个列表中的元素
__all__变量限制调用模块时使用的 *
手动调用时不限制
在写了all关键字之后,调用“*”时,只能调用all变量中的函数
但是手动调用模块中的函数也可以调用
6.总结
1.如何自定义模块并导入?
在python代码文件中正常写代码即可,通过import、from关键字和导入python内置模块一样导入即可使用
2.__main__变量的功能是?
if __main__ =="__main__"表示,只有当程序时直接执行的才会进入if内部,如果是被外界导入的,则if无法进入
3.注意事项
①不同模块,同名的功能,如果都被导入,那么后导入的会覆盖先导入的
②__all__变量,是一个列表,控制import*的时候哪些功能可以被导入
四、python包
1.什么是python包
从物理上看,包就是一个文件夹,在该文件夹上包含了一个__init__.py文件,该文件夹可用于包含多个模块文件,从逻辑上看,包的本质依然是模块
有 _init__.py文件是python包,如果没有这个文件就是一个目录文件夹
创建包后,系统会自动创建一个 _init__.py文件
2.包的作用
当我们的模块文件越来越多时,包可以帮助我们管理这些模块,包的作用就是包含多个模块,包的本质也是模块
3.快速入门
main函数
# 创建一个包 # 导入自定义的包中的模块,并使用 import My_Package.My_Module1 import My_Package.My_Module2 My_Package.My_Module1.info_print1() My_Package.My_Module2.info_print2()
新创包:
模块一:
# 演示自定义模块1 def info_print1(): print("我是自创包下的模块一的功能函数")
模块二:
# 自定义模块二 def info_print2(): print("我是自创包下的模块二的功能函数")
4.导入包
方式一:
import 包名.模块名
包名.模块名.目标
eg:my_package.my_module.test()
方式二:
from 包名 import 模块名
模块名.功能名
eg:from my_package import my_module1
my_module1.info_print1()
from my_package.my_module1 import info_print1
info_print1()
# 方式1:
import My_Package.My_Module1
import My_Package.My_Module2
My_Package.My_Module1.info_print1()
My_Package.My_Module2.info_print2()
# 方式2:
from My_Package import My_Module1
from My_Package import My_Module2
My_Module1.info_print1()
My_Module2.info_print2()
# 方式3:
from My_Package.My_Module1 import info_print1
from My_Package.My_Module2 import info_print2
info_print1()
info_print2()
方式三:
注意:必须在'__init__.py'文件中添加'__all__ = [ ] ',控制允许导入的模块列表
from 包名 import *
模块名.目标
all变量只能控制*,手动导入不受控制
总结
1.什么是python中的包?
包就是一个文件夹,里面可以存放许多python的模块(代码文件),通过包,在逻辑上将一批模块归为一类,方便使用2.__init__.py文件的作用?
创建包会默认自动创建的文件,通过这个文件来表示一个文件夹是python的包,而非普通的文件夹3.__all__变量的作用?
同模块中学习到的是一个作用,能够控制import*能够导入的内容
5.安装第三方包
1.什么是第三方包?
包可以包含一堆的python模块,而每个模块又内涵许多功能
所以,我们可以认为:一个包,就是一堆同类型功能的集合体
2.安装第三方包—pip
第三方包的安装非常简单,只需要使用python内置的pip程序即可
在命令提示符中输入:
pip install 包名称
即可通过网络快速安装第三方包
3.总结
①什么是第三方包?有什么作用?
第三方包就是非python官方内置的包,可以安装它们扩展功能,提高开发效率
②如何安装?
在命令提示符内:
pip install 包名称
pip install -i 网址 包名称
在Pycharm中安装
五、练习案例:自定义工具包
创建一个自定义包,名称位:my_utils
在包内提供两个模块:
str_util.py(字符串相关工具,内含:)
函数:str_reverse(s),接收传入字符串,将字符串反转返回
函数:substr(s,x,y),按照下标x和y,对字符串进行切片
file_util.py(文件处理相关工具,内含:)
函数:print_file_info(file_name),接收传入文件的路径,打印文件的全部内容,如文件不存在则捕获异常,输出提示信息,通过finally关闭文件对象
函数:append_to_file(file_name,data),接受文件路径以及传入数据,将数据追加写入到文件中构建出包后,尝试用一下自己编写的工具包
测试模块
# 练习案例:自定义工具包
# 创建一个自定义包,名称位:my_utils
# 在包内提供两个模块:
# str_util.py(字符串相关工具,内含:)
# 函数:str_reverse(s),接收传入字符串,将字符串反转返回
# 函数:substr(s,x,y),按照下标x和y,对字符串进行切片
# file_util.py(文件处理相关工具,内含:)
# 函数:print_file_info(file_name),接收传入文件的路径,打印文件的全部内容,如文件不存在则捕获异常,输出提示信息,通过finally关闭文件对象
# 函数:append_to_file(file_name,data),接受文件路径以及传入数据,将数据追加写入到文件中
# 构建出包后,尝试用一下自己编写的工具包
import my_utils.str_util
from my_utils import file_util
print(my_utils.str_util.str_reverse("越来越好"))
print(my_utils.str_util.substr("我一直相信",0,5))
print("\n")
file_util.print_file_info("E:/test_append.txt")
file_util.append_to_file("E:/test_append.txt","一定")
file_util.print_file_info("E:/test_append.txt")
str_util.py
# 字符串相关的工具模块
# str_util.py(字符串相关工具,内含:)
# 函数:str_reverse(s),接收传入字符串,将字符串反转返回
# 函数:substr(s,x,y),按照下标x和y,对字符串进行切片
def str_reverse(s):
'''
功能:将字符串进行反转
:param s: 被反转的字符串
:return: 反转后的字符串
'''
return s[::-1]
def substr(s,x,y):
'''
功能:按照给定的下标完成给定字符串的切片
:param s:即将被切片的字符串
:param x:切片的开始下标
:param y:切片的结束下标
:return:切片完成后的字符串
'''
return s[x:y]
if __name__ == '__main__':
print(str_reverse("一切都会好的"))
print(substr("一切都会好的",2,6))
file_util.py
# file_util.py(文件处理相关工具,内含:)
# 函数:print_file_info(file_name),接收传入文件的路径,打印文件的全部内容,如文件不存在则捕获异常,输出提示信息,通过finally关闭文件对象
# 函数:append_to_file(file_name,data),接受文件路径以及传入数据,将数据追加写入到文件中
def print_file_info(file_name):
'''
功能:将给定路径的文件内容输出到控制台中
:param file_name: 即将读取的文件路径
:return: None
'''
f =None
try:
f = open(file_name,"r",encoding='utf-8')
content = f.read()
print("文件的全部内容如下:")
print(content)
except Exception as Ex:
print(f"程序出现了异常,原因是:{Ex}")
f = open(file_name,"w",encoding='utf-8')
finally:
if f: # 如果变量是None,表示False,如果有任何内容,就是True
f.close()
def append_to_file(file_name,data):
'''
功能:将指定的数据追加到指定的文件中
:param file_name: 指定的文件的路径
:param data:指定的数据
:return:None
'''
f = open(file_name,"a",encoding="utf-8")
f.write(data)
f.write("\n")
f.close()
if __name__ == '__main__':
append_to_file("E:/test_append.txt","我一直相信,一切都会好的")