python——错误和异常
导言
学习python过程中总会遇到各种错误,但没有一个体系化讲解,这篇文章是总结python的错误和异常。
按以下路径讲解:
1.错误和异常
2.捕获异常
3.主动抛异常
4.如何分析和收集异常
资料来源:错误和异常
错误和异常
1.错误
错误通常指语法错误,在程序解析阶段会被发现。
示例
a = “python”
print(a)
File "<ipython-input-5-8c4ed26a3a35>", line 1
a = “python”
^
SyntaxError: invalid character in identifier
该错误则是中文引号错误导致 语法错误(SyntaxError)。
2.异常
异常指的是程序没有语法错误,但运行期间仍然报错。
示例TypeError
def test(a, c):
print(a+c)
if __name__ == '__main__':
test(2, 3)
test('2', 3)
显然,test('2',3)会产生格式错误,字符串+数值无法获得结果
2.1 异常在什么时候发生
异常只有遇到特定情况时才会发生错误,本身语句并没有 问题。
所以,在写程序过程中,程序员会考虑特殊情况,刻意处理边界情况或特殊情况,避免错误。
通常会使用try...except...else...finally处理,后文详细讲解。
3.异常类继承关系
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
如何捕获异常
通常程序发生异常,就会终止。
终止导致的结果:
1.后续程序应继续执行却被终止
2.无法保留异常信息
所以需要将异常捕获。
1.try
python中,捕获异常使用try ... except ...这种语法来捕捉异常,下面是一个异常捕获的示例
def test(a, b):
try:
print(a/b)
except ZeroDivisionError:
print("0不能作分母")
if __name__ == '__main__':
test(10, 5)
test(10, 0)
优化一下可以使用logging模块
2.except
except 可以指定想要捕获的异常,比如上面的例子中,代码想捕获ZeroDivisionError 异常,如果try子句中发生了别的异常,这个except 就不会捕捉。
针对不同的异常做不同的处理,你可以一次性指定想要捕获的所有异常,比如下面的代码
def test(a, b):
try:
print(a/b)
except (ZeroDivisionError, ValueError):
return None
if __name__ == '__main__':
test(10, 5)
test(10, 0)
也可以逐个捕捉
def test(a, b):
try:
print(a/b)
except ZeroDivisionError:
print('0不能做分母')
except ValueError:
print("类型错误")
else:
print('什么异常都没发生')
if __name__ == '__main__':
test(10, 5)
test(10, 0)
try ... except ... else这种语法,当没有异常发生时,就会执行else语句块里的代码。
万能用法:
def test(a, b):
try:
print(a/b)
except:
print('发生异常')
if __name__ == '__main__':
test(10, 5)
test(10, 0)
3.finally
finally是清理收尾的定位,也就是不管try..except发生什么,最终都会执行finally的代码
def divide(x, y):
try:
result = x / y
except ZeroDivisionError:
print("division by zero!")
else:
print("result is", result)
finally:
print("executing finally clause")
if __name__ == '__main__':
divide(10, 5)
divide(10, 0)
主动抛异常
1.抛异常
抛异常的使用场景通常是
1.上层调用者希望能够捕获自定义异常
2.本身并不是异常,但根据业务场景属于异常或特殊情况
示例
def divide(x, y):
if y == 0:
raise ZeroDivisionError("0不能做分母")
return x/y
if __name__ == '__main__':
divide(10, 5)
divide(10, 0)
抛出异常时,你可以指定抛出哪个异常,如果你不想指定,那么可以抛出异常Exception, 它是所有异常的父类
def divide(x, y):
if y == 0:
raise Exception("0不能做分母")
return x/y
if __name__ == '__main__':
divide(10, 5)
divide(10, 0)
2.自定义异常
import requests
class HttpCodeException(Exception):
pass
def get_html(url, headers):
res = requests.get(url, headers=headers)
print(res.status_code)
if res.status_code != 200:
raise HttpCodeException
return res.text
try:
text = get_html("http://www.coolpython.net", {})
print(text)
except HttpCodeException:
print("状态码不是200")
这样子能够更有针对性处理异常
异常信息分析与收集
1. 异常信息分析
def func_tet():
func_sum('4', 3)
def func_sum(a, b):
value = a + b
return value
func_tet()
报错信息如下:
image.png
异常信息分为两部分,红色+蓝色。
分析时,先关注最后一行蓝色框内的信息,这里的信息明确的指明了异常的类型和异常的解释信息。
第二部分,就是红色框内的内容,是调用堆栈信息,详细的记录了程序的执行路径,最后一行正是错误发生的位置。
现在,既有出错代码的位置,又有错误的类型与解释,如果还是不能找出问题,那么,可以百度了,百度时将最后一行蓝色框里的内容作为搜索词进行搜索,可以找到大量文章。