【每日一问】python异常捕获机制
为什么需要捕获异常?
找出并修改错误代码,防止程序终止。
调试Python程序时,经常会报出一些异常,异常的原因一方面可能是写程序时由于疏忽或者考虑不全造成了错误,这时就需要根据异常Traceback到出错点,进行分析改正;另一方面,有些异常是不可避免的,但我们可以对异常进行捕获处理,防止程序终止。
1 异常类型
1.1 python内置异常
BaseException #所有异常的基类
BaseException # 所有异常的基类
+-- SystemExit # 解释器请求退出
+-- KeyboardInterrupt # 用户中断执行(通常是输入^C)
+-- GeneratorExit # 生成器(generator)发生异常来通知退出
+-- Exception # 常规异常的基类
+-- StopIteration # 迭代器没有更多的值
+-- StopAsyncIteration # 必须通过异步迭代器对象的__anext__()方法引发以停止迭代
+-- ArithmeticError # 各种算术错误引发的内置异常的基类
| +-- FloatingPointError # 浮点计算错误
| +-- OverflowError # 数值运算结果太大无法表示
| +-- **ZeroDivisionError # 除(或取模)零 (所有数据类型)**
+-- AssertionError # 当assert语句失败时引发
+-- **AttributeError # 属性引用或赋值失败**
+-- BufferError # 无法执行与缓冲区相关的操作时引发
+-- EOFError # 当input()函数在没有读取任何数据的情况下达到文件结束条件(EOF)时引发
+-- ImportError # 导入模块/对象失败
| +-- ModuleNotFoundError # 无法找到模块或在在sys.modules中找到None
+-- LookupError # 映射或序列上使用的键或索引无效时引发的异常的基类
| +-- IndexError # 序列中没有此索引(index)
| +-- KeyError # 映射中没有这个键
+-- MemoryError # 内存溢出错误(对于Python 解释器不是致命的)
+-- NameError # 未声明/初始化对象 (没有属性)
| +-- UnboundLocalError # 访问未初始化的本地变量
+-- OSError # 操作系统错误,EnvironmentError,IOError,WindowsError,socket.error,select.error和mmap.error已合并到OSError中,构造函数可能返回子类
| +-- BlockingIOError # 操作将阻塞对象(e.g. socket)设置为非阻塞操作
| +-- ChildProcessError # 在子进程上的操作失败
| +-- ConnectionError # 与连接相关的异常的基类
| | +-- BrokenPipeError # 另一端关闭时尝试写入管道或试图在已关闭写入的套接字上写入
| | +-- ConnectionAbortedError # 连接尝试被对等方中止
| | +-- ConnectionRefusedError # 连接尝试被对等方拒绝
| | +-- ConnectionResetError # 连接由对等方重置
| +-- FileExistsError # 创建已存在的文件或目录
| +-- FileNotFoundError # 请求不存在的文件或目录
| +-- InterruptedError # 系统调用被输入信号中断
| +-- IsADirectoryError # 在目录上请求文件操作(例如 os.remove())
| +-- NotADirectoryError # 在不是目录的事物上请求目录操作(例如 os.listdir())
| +-- PermissionError # 尝试在没有足够访问权限的情况下运行操作
| +-- ProcessLookupError # 给定进程不存在
| +-- TimeoutError # 系统函数在系统级别超时
+-- ReferenceError # weakref.proxy()函数创建的弱引用试图访问已经垃圾回收了的对象
+-- RuntimeError # 在检测到不属于任何其他类别的错误时触发
| +-- NotImplementedError # 在用户定义的基类中,抽象方法要求派生类重写该方法或者正在开发的类指示仍然需要添加实际实现
| +-- RecursionError # 解释器检测到超出最大递归深度
+-- SyntaxError # Python 语法错误
| +-- IndentationError # 缩进错误
| +-- TabError # Tab和空格混用
+-- SystemError # 解释器发现内部错误
+-- TypeError # 操作或函数应用于不适当类型的对象
+-- ValueError # 操作或函数接收到具有正确类型但值不合适的参数
| +-- UnicodeError # 发生与Unicode相关的编码或解码错误
| +-- UnicodeDecodeError # Unicode解码错误
| +-- UnicodeEncodeError # Unicode编码错误
| +-- UnicodeTranslateError # Unicode转码错误
+-- Warning # 警告的基类
+-- DeprecationWarning # 有关已弃用功能的警告的基类
+-- PendingDeprecationWarning # 有关不推荐使用功能的警告的基类
+-- RuntimeWarning # 有关可疑的运行时行为的警告的基类
+-- SyntaxWarning # 关于可疑语法警告的基类
+-- UserWarning # 用户代码生成警告的基类
+-- FutureWarning # 有关已弃用功能的警告的基类
+-- ImportWarning # 关于模块导入时可能出错的警告的基类
+-- UnicodeWarning # 与Unicode相关的警告的基类
+-- BytesWarning # 与bytes和bytearray相关的警告的基类
+-- ResourceWarning # 与资源使用相关的警告的基类。被默认警告过滤器忽略。
1.2 requests模块的相关异常
from requests.exceptions import ConnectionError, ReadTimeout
from requests import ConnectionError, ReadTimeout
1.3 用户自定义异常
class MyError(Exception):
def _init_(self,msg):
self.msg=msg
def _str_(self):
return self.msg
try:
raise MyError('类型错误')
except MyError as e:
print('My exception occurred',e.msg)
2 异常捕获
try ……except……结构,把可能发生错误的语句放在try模块里,用except 来处理异常,每一个try,都必须至少对应一个except,此外,与python异常相关的关键字主要有:
try/except捕获异常并处理
pass忽略异常
as 定义异常实例
else 如果try中的语句没有引发异常,则执行else 中的语句
finally 无论是否出现异常,都执行的代码
raise 抛出/引发异常
2.1 捕获所有异常(慎用)
包括键盘中断和程序退出请求
try:
<语句>
except:
print('异常说明')
2.2 捕获指定异常
try:
<语句>
except <异常名ValueError>:
print('异常说明')
#万能异常
try:
<语句>
except Exception:
print('异常说明')
2.3 捕获多个异常
#不区分优先级
try:
<语句>
except (<异常名1>,<异常名2>,……):
print('异常说明')
#区分优先级
try:
<语句>
except <异常名1>:
print('异常说明1')
except <异常名2>:
print('异常说明2')
except <异常名3>:
print('异常说明3')
2.4 异常中的else
如果判断完没有某些异常后,还想做其他事,就可以使用else语句
try:
<语句>
except <异常名1>:
print('异常说明1')
else:
<语句>
2.5 异常中的finally
#finally语句是无论是否发生异常都会执行最后的代码
try:
<语句>
finally:
<语句>
str1 = 'hello world'
try:
int(str1)
except IndexError as e:
print(e)
except KeyError as e:
print(e)
except ValueError as e:
print(e)
else:
print('try内没有异常')
finally:
print('无论异常与否,都会执行我')
2.6 raise主动触发异常
raise [Exception [,args[,traceback]]]
def not_zero(num):
try:
if num == 0:
raise ValueError('参数错误')
return num
except Exception as e:
print(e)
not_zero(0)
2.7 采用traceback模块查看异常
try:
block
except:
traceback.print_exc()
另外,traceback.print_exc()跟traceback.format_exc()有什么区别呢?
区别就是,format_exc()返回字符串,print_exc()则直接给打印出来。即traceback.print_exc()与print(traceback.format_exc())效果是一样的。print_exc()还可以接受file参数直接写入到一个文件。比如可以像下面这样把相关信息写入到tb.txt文件去。
import traceback
a='Do u exist in this world?'
def ex(a):
try:
if 'I' not in a:
raise ValueError('u do not exist!')
return a
#1/0
except Exception as e:
traceback.print_exc()
ex(a)
#traceback.print_exc(file=open('tb.txt','w+'))