2.4 模块与异常
2.4.1 异常介绍
1.异常简介
程序在运行期间,当python检测到一个错误时,解释器无法继续执行,就会抛出异常。
异常不是语法错误,是运行期间遇到的非语法错误。
2.常见异常
f = open("xxx.txt", "r")
f = open("xxx.txt", "r")
FileNotFoundError: [Errno 2] No such file or directory: 'xxx.txt'
10/0
10/0
ZeroDivisionError: division by zero
2.4.2 捕获异常
1. 处理异常目的
防止程序退出,保证程序正常执行
2.捕获异常
2.1 捕获任意类型的异常
try:
可能发生异常的代码块
except:
如果发现异常跳转到处理的代码块
2.2 捕获指定异常类型
try:
print("="*30)
f = open("xxx.txt", "r")
print("="*30)
except FileNotFoundError:
print("捕获到指定异常")
输出
==============================
捕获到指定异常
2.3 捕获多个指定异常
try:
print("="*30)
f = open("xxx.txt", "r")
print("="*30)
except (FileNotFoundError,NameError):
print("捕获到指定异常")
2.4 获取异常的描述
ctrl + b
try:
print("="*30)
f = open("xxx.txt", "r")
print("="*30)
except FileNotFoundError as e:
print("捕获到指定异常,异常信息为:", e)
输出
==============================
捕获到指定异常,异常信息为: [Errno 2] No such file or directory: 'xxx.txt'
2.5 捕获任意类型的异常并且获取信息
try:
print("="*30)
f = open("xxx.txt", "r")
print("="*30)
except Exception as e:
print("捕获到指定异常,异常信息为:", e)
Exception是所有错误类的继承,还有个BaseException
2.6 异常中的else
如果没有发生异常则执行else后代码
try:
num = 100
print(num)
except NameError as errorMsg:
print('产生错误了:%s'%errorMsg)
else:
print('没有捕获到异常,真高兴')
2.7 异常中的finally
无论异常发生或者没有,均会在最后执行finally里的代码块
2.8 应用
f = open('yyy.txt', 'w') # 前提是,成功打开文件
try:
# ret = f.read()
# print(ret)
f.write('hello mike')
print('='*20)
except Exception as e:
print('产出异常,异常信息为:', e)
else:
print('没有产生异常')
finally:
print('不管有没有异常,都要关闭文件')
f.close()
2.4.3 传递异常
1.异常传递特点
如果异常在内部产生,如果内部不做捕获处理,这个异常会向外部传递。
2.try嵌套
如果内层try没有捕获处理该异常,就会向外层try传递。
try:
f = open("xxx.txt", "w")
try:
f.read()
finally:
print("内层异常无论发生与否的处理")
except Exception as e:
print("外层发生了异常,异常信息为:", e)
else:
print("异常没有发生")
finally:
print("外层异常无论发生与否的处理")
输出
内层异常无论发生与否的处理
外层发生了异常,异常信息为: not readable
外层异常无论发生与否的处理
3.函数嵌套
如果内层函数没有捕获处理该异常,就会向外层函数进行传递
def test01():
print("test01start")
print(num)
print("test01end")
def test02():
print("test02start")
test01()
print("test02end")
def test03():
print("test03start")
try:
test02()
except Exception as e:
print("异常信息为:", e)
else:
print("没有异常发生")
finally:
print("test03end")
test03()
输出
test03start
test02start
test01start
异常信息为: name 'num' is not defined
test03end
2.4.4 自定义的异常
1.抛出自定义的异常
- 用户可以用raise语句来人为抛出一个异常
- 异常错误对象必须要有一个名字,且应该是Exception的子类
格式如下
# 1. 自定义异常类
class 自定义异常类名字(Exception):
1.1 重新写__init__(self, 形参1, 形参2,……)
# 建议调用父类的init,先做父类的初始化工作
super().__init__()
咱们自己写的代码
1.2 重新写__str__(),返回提示信息
# 2. 抛出异常类
raise 自定义异常类名字(实参1, 实参2,……)
实例:
class TelNumberLenthError(Exception):
def __init__(self,_user_len,_match_len = 11):
super().__init__()
self.user_len = _user_len
self.match_len = _match_len
# 先调用父类的方法进行初始化
# 再写自己的初始化
def __str__(self):
return f"用户的电话长度为{self.user_len}位,不是要求的{self.match_len}位"
try:
num_str = input("请输入您的号码:")
if len(num_str) != 11:
raise TelNumberLenthError(len(num_str))
except Exception as e:
print("异常信息位:", e)
else:
print("没有错误")
输出如下
请输入您的号码:11
异常信息位: 用户的电话长度为2位,不是要求的11位
2.4.5 模块
1. 模块介绍
- 模块是一个由Python代码组成的文件,就是一个以
.py
结尾的文件。 - 模块包含函数、类和变量,还可以包括可运行的代码。
- 模块的主要作用:
- 提高了代码的可维护性
- 一个模块编写完毕之后,其他模块直接调用,不用再从零开始写代码了,节约了工作时间
- 避免名字冲突,可以再不同的模块里同时调用
2. 模块的使用
2.1 import 导入模块
导入格式
import 模块名
使用格式
模块名.方法名
2.2 from … import…导入模块里需要的内容
导入格式
from 模块名 import 函数名1,函数名2,`````
使用格式
导入的函数名()
# 导入自己所需的函数,没导入的不可用
导入格式
from 模块名 import *
使用格式
导入的函数名()
# 这是导入所有的函数(但是一般模块会有限制,会限制部分不在全部导入里),一般不用,极可能造成同名冲突
会去查到对应模块里 是否有__all__,有则导入里面包含的元素,没有才是导入全部。
2.3 俩个导入的区别
- import 导入模块,会把整个模块导入进去
- from … import … 只导入所需函数
2.4 import…as…能够给导入的模块命名
- 将名称简化
- 防止重名冲突
import random as r
ret = r.randint(1,3)
print(ret)
from random import randint as r
ret = r.(1,3)
print(ret)
强烈建议使用第二种方式直接导入工具名的时候切记要给工具起别名 ,以防止冲突。
- import里导入的是默认同级目录的最为优先。
- 当前路径找不到才会去找系统路径。
2.5 模块搜索路径存储在 system模块里的sys.path
变量中
import sys
print(sys.path)
输出
['E:\\Project\\pythonProject', 'E:\\Project\\pythonProject', 'E:\\Program Files\\JetBrains\\PyCharm 2020.2.3\\plugins\\python\\helpers\\pycharm_display', 'C:\\Users\\songs\\AppData\\Local\\Programs\\Python\\Python38\\python38.zip', 'C:\\Users\\songs\\AppData\\Local\\Programs\\Python\\Python38\\DLLs', 'C:\\Users\\songs\\AppData\\Local\\Programs\\Python\\Python38\\lib', 'C:\\Users\\songs\\AppData\\Local\\Programs\\Python\\Python38', 'C:\\Users\\songs\\AppData\\Local\\Programs\\Python\\Python38\\lib\\site-packages', 'E:\\Program Files\\JetBrains\\PyCharm 2020.2.3\\plugins\\python\\helpers\\pycharm_matplotlib_backend']
可以看出第一个搜索的就是当前路径的文件夹,然后一次寻找到pycharm里的,还有python解释器里的自带的包和第三方的包。
快捷查看的可以点project下面那个External Libraries
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3M54qBjF-1610885212938)(\asset\Snipaste_2020-10-30_17-00-07.png)]
2.6 更改模块搜索路径的顺序
从上一节我们可以得出,这个搜索路径的顺序是列表,既然是列表,我们就可以对其进行更改
import sys
print(sys.path)
sys.path.insert(0, 'C:\\xxx\\xxx\\xxxxx\\xxxxxx\\xx')
3. 制作模块
3.1 制作自己定义的模块
把写好的代码放进去一个.py
文件中,记住命名得符合规格。
def my_add(a, b):
"""返回2个数相加结果"""
return a+b
def my_sub(a, b):
"""返回2个数相减结果"""
return a-b
3.2 导入自己自定义的模块
import自己定制的模块
import module # 导入模块
# 调用模块中的函数
ret = module.my_add(1, 1)
print(ret)
ret = module.my_sub(10, 20)
print(ret)
3.3 测试模块
模块里可以自己测试自己功能,测试成功后再导入其他文件里使用测试。
def my_add(a, b):
"""返回2个数相加结果"""
return a+b
def my_sub(a, b):
"""返回2个数相减结果"""
return a-b
ret = my_add(2, 2)
print('模块中测试代码:my_add(2, 2) = ', ret)
ret = my_sub(10, 2)
print('模块中测试代码:my_sub(10, 2) = ', ret)
但是别人导入模块的时候,也会把测试代码也会执行一次,这样子不符合我们对模块的需求。
- 模块文件,应该是单独运行的时候才执行测试代码。
- 作为模块文件被导入的时候,不执行测试代码。
- python中的
__name__
能解决上述问题
3.4 模块里的__name__
print('module.py文件中:', __name__)
# 当独自运行的时候结果为 __main__,且为str。
# 当被导入的时候,为文件名而非__main__。
因此我们可以把测试的代码放在if __name__ =='__main__'
的条件语句里
这样单独运行的时候测试代码会执行。
如果是导包的时候,不会运行测试代码。
导入的模块里
#print('module.py文件中:', __name__)
# 当独自运行的时候结果为 __main__
# 当被导入的时候,为文件名而非__main__
def my_add(a, b):
return a + b
def my_sub(c, d):
return c - d
if __name__ == '__main__':
n1 = 10
n2 = 20
print(my_add(n1, n2))
print(my_sub(n1, n2))
导入模块的文件里
import module1
n1 = 40
n2 = 50
print(module1.my_add(n1, n2))
print(module1.my_sub(n1, n2))
快捷写法就是在模块空白处敲main然后回车,会自动生成测试条件语句。
3.5 模块里的__all__
变量
-
模块中
__all__
变量,只对from xxx import *
这种导入方式有效 -
模块中
__all__
变量包含的元素,才能会被from xxx import *
导入 -
__all__
格式:__all__ = ['变量名', '类名', '函数名', ……]