Python错误 try语句
程序运行中遇到的错误通常有3类:
1,程序编写有问题造成的错误,称之为Bug,这种是必须修复的。 debug:调试
注意:bug是程序本身有问题、有缺陷、系统漏洞。
2,用户输入错误。
3,还有一类错误是完全无法在程序运行中预测的错误,例如写入文件的时候,磁盘满了,写不进去了,或者从网络抓取数据时,网络突然断掉了。这类错误也称为异常,在程序中通常是必须处理的,否则,程序会因为各种问题终止并退出。
有时我们也需要跟踪程序的执行,查看变量的值是否正确,这个过程称为调试。Python的pdb可以让我们以单步方式执行代码。
*为了清晰和准确,try块中应该只抛出预期异常的语句。
try语句的一般形式、except语句的几种用法:
#try语句的一般形式 try: <语句> # 要捕捉异常的语句 except 异常1: # 要进行处理的异常 <语句> # 对异常进行处理的语句 except 异常2: <语句> else: <语句> # 如果异常没有被触发,则执行该语句 finally: <语句> # 不管异常是否触发,都执行finally语句 #except语句的几种用法: except: except <异常>: except (异常1,异常2): except <异常> as <数据>: except (异常1,异常2) as <数据>:
Python中常用的内置异常
| 异常名 | 描述 |
| AttributeError | 调用不存在的方法引发的异常 |
| EOFError | 遇到文件末尾引发的异常 |
| ImportError | 导入模块出错引发的异常 |
| IndexError | 列表越界引发的异常 |
| IOError | I/O操作引发的异常,如打开文件出错等 |
| KeyError | 使用字典中不存在的关键字引发的异常 |
| NameError | 使用不存在的变量名引发的异常 |
| TabError | 语句块缩进不正确引发的异常 |
| ValueError | 搜索列表中不存在的值引发的异常 |
| ZeroDivisionError | 除数为零引发的异常 |
try ……except……else……finally……
1,可以有多个except语句块,用来捕获不同类型的错误。
2,except语句块后面可以跟一个else,当没有错误发生时,才会执行else语句;如果有错误发生则不会执行else语句。
3,finally语句块:不论错误是否发生,只要有该语句,则一定会被执行。
4,Python所有的错误都是从BaseException类派生的。
Python的错误其实也是class,所有的错误类型都继承自BaseException,所以在使用except语句块时需要注意,它不但捕获该类型的错误,还把其子类也“一网打尽”。
UnicodeError是ValueError的子类
5,不需要在每个可能出错的地方去捕获错误,只要在合适的层次去捕获错误就可以了。
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
调用栈
出错的时候,一定要分析错误的调用栈信息,才能定位错误的位置。
Traceback (most recent call last): 这是错误的跟踪信息
如果错误没有被捕获,它就会一直往上抛,最后被Python解释器捕获,打印一个错误信息,然后程序退出。
记录错误
目的:希望程序出错后,打印出错误堆栈,让程序继续执行下去。
logging模块:把错误记录到日志文件里,方便事后排查。
抛出错误,raise语句
格式:raise 错误类型() ,错误类型,即是参数
(1)因为错误是class,捕获一个错误就是捕获到该class的一个实例。
(2)在bar( )函数中,我们明明已经捕获了错误,但是打印一个ValueError!后,又把错误通过raise语句抛出去了,这不有病么?
其实这种错误处理方式不但没病,而且相当常见。捕获错误目的只是记录一下,便于后续追踪。但是,由于当前函数不知道应该怎么处理该错误,所以,最恰当的方式是继续往上抛,让顶层调用者去处理。好比一个员工处理不了一个问题时,就把问题抛给他的老板,如果他的老板也处理不了,就一直往上抛,最终会抛给CEO去处理。
(3)raise语句如果不带参数,就会把当前错误原样抛出。此外,在except中raise一个Error时,还可以把一种类型的错误转化成另一种类型:
只要是合理的转换逻辑就可以,但是,决不应该把一个IOError转换成毫不相干的ValueError。
………………………………………………………………………………………………
文档测试
Python内置的“文档测试”(doctest)模块可以直接提取注释中的代码并执行测试。
