捕获错误
捕获错误:try…except…finally…
这套机制的运行有点类似 if
try: 将可能出错的代码块放在里面 代码会在try里面运行,直达发生错误,立即终止运行
except 错误类型: 当try捕获到某个特定错误时,转跳到except并运行里面的代码。 如果没有发生错误则会被忽略 错误类型: ZeroDivisionError:除零错误 TypeError:类型错误 Exception :任意错误
finally: 当except运行完后,如果有finally,则会运行这部分
print("start")try:print("发生错误之前")y = 5/0 # 分母为0的错误,try捕获到ZeroDivisionErrorprint("发生错误之后")passexcept 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/0obj = 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 funcself.__function()File "E:\Projects Files\Py_2020_12_05\PythonApplication2\PythonApplication2\play.py", line 6, in __functiony = 4/0ZeroDivisionError: division by zero
保存记录:logging
如果用上述方法,有一个问题, 那就是只要遇到错误,整个程序就中止了。 如果想不让他中止用try,又不能返回异常栈怎么办?
Python内置logging模块,可以保存记录
import loggingprint("开始处理异常")try:y = 5/0except Exception as e:logging.exception(e)print("异常处理完成")
开始处理异常ERROR:root:division by zeroTraceback (most recent call last):File "E:\Projects Files\Py_2020_12_05\PythonApplication2\PythonApplication2\play.py", line 4, in <module>y = 5/0ZeroDivisionError: 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 funcraise 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 logginglogging.debug("A-Debug")logging.info("B-Info")logging.warning("C-Warning")logging.error("D-Error")logging.critical("E-Critiacl")
#输出#==================================WARNING:root:C-WarningERROR:root:D-ErrorCRITICAL:root:E-Critiacl
Logging:设置安全级别
如果希望输出安全等级低的info、debug等,可以使用basicConfig设置安全等级
import logginglogging.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-DebugINFO:root:B-InfoWARNING:root:C-WarningERROR:root:D-ErrorCRITICAL: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 logginglogging.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-Debug2021-02-07 20:00:05,008 - play.py[line:5] - INFO: B-Info2021-02-07 20:00:05,009 - play.py[line:6] - WARNING: C-Warning2021-02-07 20:00:05,009 - play.py[line:7] - ERROR: D-Error2021-02-07 20:00:05,009 - play.py[line:8] - CRITICAL: E-Critiacl
Pdb:跟踪程序
如果程序是在IDE中测试的,我们可以直接设置断点进行跟踪
但如果是在控制台中,就不能使用IDE的断点功能了 此时,可以使用pdb模块中的pdb.set_trace( )方法设置断点 每次输入n,会自动执行下一句,返回跟踪信息,并再次暂停
import pdbprint("output-A")print("output-B")pdb.set_trace()print("output-C")print("output-D")
#输出#==================================output-Aoutput-B> e:\projects files\py_2020_12_05\pythonapplication2\pythonapplication2\play.py(5)<module>()-> print("output-C")(Pdb) noutput-C> e:\projects files\py_2020_12_05\pythonapplication2\pythonapplication2\play.py(6)<module>()-> print("output-D")(Pdb) noutput-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 _agFile "D:\Program Files (x86)\Microsoft Visual Studio\Shared\Python36_64\lib\bdb.py", line 53, in trace_dispatchFile "D:\Program Files (x86)\Microsoft Visual Studio\Shared\Python36_64\lib\bdb.py", line 85, in dispatch_callFile "D:\Program Files (x86)\Microsoft Visual Studio\Shared\Python36_64\lib\pdb.py", line 251, in user_callFile "D:\Program Files (x86)\Microsoft Visual Studio\Shared\Python36_64\lib\pdb.py", line 343, in interactionAttributeError: 'NoneType' object has no attribute '_previous_sigint_handler'

