一、异常的概述
- 异常:程序出现的错误。
- 异常类:用来描述某一类型的异常;Python 解释器提供了很多异常类,用来描述那些常见的异常的。
- 处理异常的原因:如果异常没被处理,会影响后面代码的执行。
二、解释器处理异常的原因
def func1():
list1 = [1, 2]
print(list1)
print("数字为%d"%"hello")
print("world")
def func2():
func1()
func2()
- Python 解释器会在出错的那一行代码的位置,根据出错的原因,创建异常的对象,然后向外抛出异常对象,抛给它的调用者。
- func1() 接收到这个异常对象,自己没处理,又把异常对象向外抛出,抛给它的调用者。
- func2() 接收到异常对象后,自己没处理,又抛给它的调用者。
- 最后是 Python 解释器接收到这个异常对象,在控制台打印出异常信息,终止程序的运行,退出解释器。
三、处理异常的基本格式
"""
基本格式:
try:
可能出现异常的代码块
except:
处理异常的代码块
执行流程:
如果"可能出现异常的代码块"出现了异常,就执行"处理异常的代码块"
否则不执行
这个格式可以处理任何一种异常
"""
四、处理指定类型的异常
"""
处理指定类型的异常:
try:
可能会出现异常的代码块
except (异常类1, 异常类2, ……) as 异常对象名:
处理异常的代码块
"""
print("start!")
try:
print(1/0)
f = open("a.txt", "r")
# except (ZeroDivisionError, FileNotFoundError) as e:
except Exception as e:
print("ed")
print(e)
print("over!")
五、else 语句
"""
else 语句的格式:
try:
可能会出现异常的代码块
except (异常类1, 异常类2, ……) as 异常对象名:
处理异常的代码块
else:
没有出现异常时,才会执行的代码块
使用场景:
通常用来检测是否出现异常了
"""
l = [10, 20]
try:
print(l[1])
except:
print("索引越界!")
else:
print("索引没有越界!")
六、finally语句
"""
finally 语句的格式:
try:
可能出现异常的代码块
except (异常类1, 异常类2, ……) as 异常对象名:
处理异常的代码块
finally:
不管是否出现异常,也不管是否捕获到异常,一定会执行的代码块
使用场景:
1. 关闭文件
2. 关闭数据库连接
"""
l = [1, 2, 3]
try:
print(l[3])
except:
print("索引越界!")
finally:
print("我会执行!")
举个栗子:
f = None
try:
f = open("mac.txt", "r")
f.write("hello")
except Exception as e:
print(e)
finally:
f.close()
七、异常的跨函数传递
"""
如果里面一层函数出现了异常,自己没有处理,那么异常对象就会传递到外面一层函数
如果里面一层函数把异常处理掉了,那么异常对象就不会向外传递了
"""
def func1():
print("func1 start")
print(10/0)
print("func1 over")
def func2():
print("func2 start")
func1()
print("func2 over")
try:
func2()
except Exception as e:
print(e)
print("last row")
八、自定义异常类
"""
自定义异常类的原因:
python 解释器自带的异常类不能满足需要
自定义异常类的步骤:
1. 定义一个类,集成一个异常类
2. 在这个类中,添加一个 __init__ 方法
"""
class Student:
def __init__(self, name, age, gender):
self.name = name
self.__age = age
self.gender = gender
def set_age(self, age):
if 0 <= age < 150:
self.__age = age
else:
raise AgeError("年龄不合法!")
class AgeError(Exception):
def __init__(self, mesg):
self.mesg = mesg
st = Student(100, "kf", "F")
print(st.set_age(200))
九、模块的基本使用
"""
在 Python 语言中,一个 .py 文件就是一个模块
模块文件中可以定义全局变量、函数、类
导入模块的原因:
在自己的程序文件中,调用另外一个程序文件中的全局变量、函数、类
导入模块的基本格式:
import 模块名
调用格式:
模块名.全局变量
模块名.函数(实参1, 实参2, ……)
模块名.类(实参1, 实参2, ……)
"""
# module1.py:
a = 100
def func1(a, b):
return a+b
class Student:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return f"name={self.name}, age={self.age}"
print("模块1")
# im.py:
import module1
print(module1.a)
s = module1.Student("ss", 20)
print(s)
十、from……import…… 导入模块
"""
导入格式:
from 模块名 import 全局变量, 函数, 类
访问格式:
全局变量
函数(实参1, 实参2, ……)
类(实参1, 实参2, ……)
从模块名导入指定内容;内容:全局变量,函数,类
"""
# eg
from module1 import a
from module2 import a as a2, func1 as f2_1
十一、from……import…… * 导入模块
"""
导入格式:
from 模块名 import *
* 是通配符,表示模块文件中所有的内容
访问格式:
全局变量
函数(实参1, 实参2, ……)
类(实参1, 实参2, ……)
从模块名导入指定内容;内容:全局变量,函数,类
"""
# module1.py
__all__ = ["a", "func1"] # 控制以 from 模块名 import * 这种格式导入的内容的
十二、__name__ 的作用
"""
主动执行文件:
正在执行的文件
__name__ 为 "__main__"
被动执行文件:
被导入的模块文件
__name__ 为模块名
"""
# 主动执行时才执行的代码
if __name__ == "__main__":
print("test1")
十三、模块的搜索路径
当导入一个模块,Python 解释器的模块位置的搜索顺序是:
- 当前目录;
- 如果不在当前目录,Python 则搜索在 shell 变量 PYTHONPATH 的每个目录;
- 如果都找不到,Python 会查看默认路径,UNIX 下,默认路径一般为 /usr/local/lib/python/;
- 模块搜索路径存储在 System 模块的 sys path 变量中,变量里包含当前目录,PYTHONPATH 和由安装过程决定的默认目录。