捕获错误
捕获错误:try…except…finally…
这套机制的运行有点类似 if
try: 将可能出错的代码块放在里面 代码会在try里面运行,直达发生错误,立即终止运行
except 错误类型: 当try捕获到某个特定错误时,转跳到except并运行里面的代码。 如果没有发生错误则会被忽略 错误类型: ZeroDivisionError:除零错误 TypeError:类型错误 Exception :任意错误
finally: 当except运行完后,如果有finally,则会运行这部分
print("start")
try:
print("发生错误之前")
y = 5/0 # 分母为0的错误,try捕获到ZeroDivisionError
print("发生错误之后")
pass
except SyntaxError: # 不是try捕获的错误类型
print("A-报告错误")
except ZeroDivisionError: # 是try捕获的错误类型,运行该部分
print("B-报告错误")
finally:
print("错误处理完成")
print("Done")
#输出
#=================================
发生错误之前
B-报告错误
错误处理完成
print("start")
try:
print("发生错误之前")
y = 5/1 # 没有捕获到错误,继续运行
print("发生错误之后")
except ZeroDivisionError: # 跳过
print("B-报告错误")
finally: # 执行
print("错误处理完成")
print("Done")
#输出
#=================================
start
发生错误之前
发生错误之后
错误处理完成
返回错误:except … as …
当except捕获到错误后,可让except把错误信息储存到一个变量内
except 错误类型 as 变量
try:
y = 5/1 # 没有捕获到错误,继续运行
except ZeroDivisionError as e: # 跳过
print("ZeroDivisionError:", e)
#输出
#=================================
ZeroDivisionError: division by zero
异常栈
假如我们不用try捕获异常,异常会从开始的位置一层一层的上抛,并记录下来 直到被最外层的python解释器捕获。并打印出来(打印出来的跟踪信息就是异常栈)
class Name(object):
def func(self):
self.__function()
def __function(self):
y = 4/0
obj = Name()
obj.func()
#输出异常栈
#=============================================================
Traceback (most recent call last):
File "E:\Projects Files\Py_2020_12_05\PythonApplication2\PythonApplication2\play.py", line 9, in <module>
obj.func()
File "E:\Projects Files\Py_2020_12_05\PythonApplication2\PythonApplication2\play.py", line 3, in func
self.__function()
File "E:\Projects Files\Py_2020_12_05\PythonApplication2\PythonApplication2\play.py", line 6, in __function
y = 4/0
ZeroDivisionError: division by zero
保存记录:logging
如果用上述方法,有一个问题, 那就是只要遇到错误,整个程序就中止了。 如果想不让他中止用try,又不能返回异常栈怎么办?
Python内置logging模块,可以保存记录
import logging
print("开始处理异常")
try:
y = 5/0
except Exception as e:
logging.exception(e)
print("异常处理完成")
开始处理异常
ERROR:root:division by zero
Traceback (most recent call last):
File "E:\Projects Files\Py_2020_12_05\PythonApplication2\PythonApplication2\play.py", line 4, in <module>
y = 5/0
ZeroDivisionError: division by zero
异常处理完成
抛出错误
抛出错误:raise
有时候我们需要特意去抛出一个错误 可以用关键字raise
使用raise上抛错误,同样可以被捕获和跟踪
def func(val):
if val == 0:
print("值为0开始抛出错误")
raise ZeroDivisionError("val == %s" %val)
else:
print("值不为0不抛出错误")
func(0)
print("程序结束")
#输出
#=============================================================
值为0开始抛出错误
Traceback (most recent call last):
File "E:\Projects Files\Py_2020_12_05\PythonApplication2\PythonApplication2\play.py", line 7, in <module>
func(0)
File "E:\Projects Files\Py_2020_12_05\PythonApplication2\PythonApplication2\play.py", line 4, in func
raise ZeroDivisionError("val == %s" %val)
ZeroDivisionError: val == 0
#=============================================================
当程序遇到raise后抛出错误终止运行了
如果没有遇到raise就不会抛出
def func(val):
if val == 0:
print("值为0开始抛出错误")
raise ZeroDivisionError("val == %s" %val)
else:
print("值不为0不抛出错误")
func(10)
print("程序结束")
#输出
#=============================================================
值不为0不抛出错误
程序结束
错误类:BaseException
错误也是一个类,也具有继承关系
所有的错误都继承于BaseException 基类可以捕获到子类的错误 子类不能捕获到基类的错误
错误继承关系表
BaseException
+-- SystemExit
+-- KeyboardInterrupt
+-- GeneratorExit
+-- Exception
+-- StopIteration
+-- StopAsyncIteration
+-- ArithmeticError
| +-- FloatingPointError
| +-- OverflowError
| +-- ZeroDivisionError
+-- AssertionError
+-- AttributeError
+-- BufferError
+-- EOFError
+-- ImportError
| +-- ModuleNotFoundError
+-- LookupError
| +-- IndexError
| +-- KeyError
+-- MemoryError
+-- NameError
| +-- UnboundLocalError
+-- OSError
| +-- BlockingIOError
| +-- ChildProcessError
| +-- ConnectionError
| | +-- BrokenPipeError
| | +-- ConnectionAbortedError
| | +-- ConnectionRefusedError
| | +-- ConnectionResetError
| +-- FileExistsError
| +-- FileNotFoundError
| +-- InterruptedError
| +-- IsADirectoryError
| +-- NotADirectoryError
| +-- PermissionError
| +-- ProcessLookupError
| +-- TimeoutError
+-- ReferenceError
+-- RuntimeError
| +-- NotImplementedError
| +-- RecursionError
+-- SyntaxError
| +-- IndentationError
| +-- TabError
+-- SystemError
+-- TypeError
+-- ValueError
| +-- UnicodeError
| +-- UnicodeDecodeError
| +-- UnicodeEncodeError
| +-- UnicodeTranslateError
+-- Warning
+-- DeprecationWarning
+-- PendingDeprecationWarning
+-- RuntimeWarning
+-- SyntaxWarning
+-- UserWarning
+-- FutureWarning
+-- ImportWarning
+-- UnicodeWarning
+-- BytesWarning
+-- ResourceWarning
https://docs.python.org/3/library/exceptions.html#exception-hierarchy
调试错误:
断言:assert
功能:当满足条件时,抛出错误 (类似 if 和 raise 的结合体)
特点: 相比if…raise,断言assert可以通过python解释器关闭,使其失效 (这时assert就等价于pass语句了) (assert会在Relsese阶段被关闭,但注意通常还是手动全部删掉比较好)
语法:
assert 返回值是布尔的表达式 , [可选参数,一般放错误说明]
assert False,"触发错误" # 类似与使用if...raise
#if True:
# raise AssertionError("触发错误")
#输出
#==================================
Traceback (most recent call last):
File "E:\play.py", line 1, in <module>
assert False,"触发错误"
AssertionError: 触发错误
错误日志
Logging:输出到控制
下面几个语句,和print( )类似 只不过,根据安全级别不同,可以控制是否输出(默认比warning低的不输出)
debug: 调试,打印所有信息,一般用于诊断问题 info: 正常运行输出的日志 warning: 目前运行正常,但有可能会出问题 error: 已经出现了一些问题 critical: 出现严重的问题,可能导致程序崩溃
import logging
logging.debug("A-Debug")
logging.info("B-Info")
logging.warning("C-Warning")
logging.error("D-Error")
logging.critical("E-Critiacl")
#输出
#==================================
WARNING:root:C-Warning
ERROR:root:D-Error
CRITICAL:root:E-Critiacl
Logging:设置安全级别
如果希望输出安全等级低的info、debug等,可以使用basicConfig设置安全等级
import logging
logging.basicConfig(level=logging.DEBUG) # 设置安全级别
logging.debug("A-Debug")
logging.info("B-Info")
logging.warning("C-Warning")
logging.error("D-Error")
logging.critical("E-Critiacl")
#输出
#==================================
DEBUG:root:A-Debug
INFO:root:B-Info
WARNING:root:C-Warning
ERROR:root:D-Error
CRITICAL:root:E-Critiacl
配置输出format格式 %(levelno)s: 打印日志级别的数值 %(levelname)s:: 打印日志级别名称 %(pathname)s: 打印当前执行程序的路径,其实就是sys.argv[0]
%(filename)s: 打印当前执行程序名
%(funcName)s: 打印日志的当前函数
%(lineno)d: 打印日志的当前行号
%(asctime)s: 打印日志的时间
%(thread)d: 打印线程ID
%(threadName)s: 打印线程名称
%(process)d: 打印进程ID
%(message)s: 打印日志信息
import logging
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s')
logging.debug("A-Debug")
logging.info("B-Info")
logging.warning("C-Warning")
logging.error("D-Error")
logging.critical("E-Critiacl")
2021-02-07 20:00:05,008 - play.py[line:4] - DEBUG: A-Debug
2021-02-07 20:00:05,008 - play.py[line:5] - INFO: B-Info
2021-02-07 20:00:05,009 - play.py[line:6] - WARNING: C-Warning
2021-02-07 20:00:05,009 - play.py[line:7] - ERROR: D-Error
2021-02-07 20:00:05,009 - play.py[line:8] - CRITICAL: E-Critiacl
Pdb:跟踪程序
如果程序是在IDE中测试的,我们可以直接设置断点进行跟踪
但如果是在控制台中,就不能使用IDE的断点功能了 此时,可以使用pdb模块中的pdb.set_trace( )方法设置断点 每次输入n,会自动执行下一句,返回跟踪信息,并再次暂停
import pdb
print("output-A")
print("output-B")
pdb.set_trace()
print("output-C")
print("output-D")
#输出
#==================================
output-A
output-B
> e:\projects files\py_2020_12_05\pythonapplication2\pythonapplication2\play.py(5)<module>()
-> print("output-C")
(Pdb) n
output-C
> e:\projects files\py_2020_12_05\pythonapplication2\pythonapplication2\play.py(6)<module>()
-> print("output-D")
(Pdb) n
output-D
--Return--
> e:\projects files\py_2020_12_05\pythonapplication2\pythonapplication2\play.py(6)<module>()->None
-> print("output-D")
(Pdb) n
--Call--
Exception ignored in: <async_generator object _ag at 0x00000267E65A41E8>
Traceback (most recent call last):
File "D:\Program Files (x86)\Microsoft Visual Studio\Shared\Python36_64\lib\types.py", line 27, in _ag
File "D:\Program Files (x86)\Microsoft Visual Studio\Shared\Python36_64\lib\bdb.py", line 53, in trace_dispatch
File "D:\Program Files (x86)\Microsoft Visual Studio\Shared\Python36_64\lib\bdb.py", line 85, in dispatch_call
File "D:\Program Files (x86)\Microsoft Visual Studio\Shared\Python36_64\lib\pdb.py", line 251, in user_call
File "D:\Program Files (x86)\Microsoft Visual Studio\Shared\Python36_64\lib\pdb.py", line 343, in interaction
AttributeError: 'NoneType' object has no attribute '_previous_sigint_handler'