python错误处理—try…catch…finally、调用栈分析
高级语言包括python一般都内置了一套try…catch…finally的错误处理机制:
>>> try:
... print('try...')
... r = 10 / 0
... print('result:', r)
... except ZeroDivisionError as e:
... print('except:', e)
... finally:
... print('finally...')
...
try...
except: division by zero
finally...
如果认为某些代码可能会出错,可以用try来运行这段代码;
如果try的代码块出现错误,则try代码省下的代码不会继续执行,而是直接跳转到catch代码块,catch就是错误处理代码块(如果没有错误,则不执行)
如果还有finally代码块,则执行finally代码块。没有则不执行
我们看到代码执行 10 / 0 的时候出现了错误(0不能作为除数),下面测试没有错误的情况
>>> try:
... print('try……')
... r = 10 / 2
... print('结果:%s' % r)
... except ZeroDivisionError as e:
... print('发生了异常:',e)
... finally:
... print('最后执行……')
...
try……
结果:5.0
最后执行……
如果try代码块可能出现多种错误类型,可以编写多个except代码块来处理;此外,如果没有发生错误,还可以在except代码块后面加上else语句,当没有错误的时候,会自动执行else语句:
>>> try:
... print('开始:')
... r = 10 / int('')
... print('结果:',r)
... except ValueError as e:
... print('ValueError:',e)
... except ZeroDivisionError as e:
... print('ZeroDivision:',r)
... else:
... print('没有出错!')
... finally:
... print('最后要执行的代码')
...
开始:
结果: 5.0
没有出错!
最后要执行的代码
万物皆对象,python的错误也是class,所有的错误类型都继承自BaseException,各个类型的错误之间可能会存在继承关系,比如UnicodeError是ValueError的子类,如果catch语句中同时出现了这两个错误,且UnicodeError在ValueError的后面处理的,那么永远都捕获不到UnicodeError。
下面是python中内置的常用错误类型继承关系:
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
使用try…catch…捕获错误一个好处就是,可以跨层调用,比如main()调用foo(),foo()调用bar(),而错误是在bar中出现的,最后我们只需要在main()中捕获就行:
>>> def foo(s):
... return 10 / int(s)
...
>>> def bar(s):
... return foo(s)*2
...
>>> def main():
... try:
... bar('')
... except Exception as e:
... print('Error:',e)
... finally:
... print('最终要执行的代码')
...
>>> main()
Error: division by zero
最终要执行的代码
调用栈
如果没有捕捉错误,该错误就会一直往上抛,最后被python解释器捕获,并打印一条错误消息,然后退出程序。下面新建一个err.py文件:
def foo(s):
return 10 / int(s)
def bar(s):
return foo(s) * 2
def main():
bar('') main()
执行结果:
PS E:\Python3.6.3\workspace> python err.py
Traceback (most recent call last):
File "err.py", line 8, in <module>
main()
File "err.py", line 6, in main
bar('')
File "err.py", line 4, in bar
return foo(s) * 2
File "err.py", line 2, in foo
return 10 / int(s)
ZeroDivisionError: division by zero
上面的信息我们可以看到整个错误的函数调用栈:
错误第一行:
Traceback (most recent call last):
告诉我们以下是错误的跟踪信息。
第2~3行:
File "err.py", line 8, in <module>
main()
告诉我们err.py执行中,main()出错了,在代码的第8行。
第4~5行:
File "err.py", line 6, in main
bar('')
告诉我们错误原因是第6行代码。
依次往下,最终告诉我们是foo函数出错了:
File "err.py", line 2, in foo
return 10 / int(s)
这就是错误的源头,因为控制台打印了错误类型:
ZeroDivisionError: division by zero
这是个ZeroDivisionError,我们分析并不是Int(s)本身定义或者语法有错误,而是int(s)返回值为0,从而找到了源头。
上面说了当我们在程序中不捕获错误的时候,python解释器会在自动打印错误的堆栈,但是程序也会戛然而止。我们可以选择把错误堆栈打印出来,同时程序会继续执行下去。怎么操作呢?python内置的logging模块可以非常清楚的记录错误信息,新建一个err_logging.py文件:
import logging
def foo(s):
return 10 / int(s)
def bar(s):
return foo(s)*2
def main():
try:
bar('')
except Exception as e:
logging.exception(e) main()
print('最后执行了……')
执行结果:
ERROR:root:division by zero
Traceback (most recent call last):
File "err_logging.py", line 8, in main
bar('')
File "err_logging.py", line 5, in bar
return foo(s)*2
File "err_logging.py", line 3, in foo
return 10 / int(s)
ZeroDivisionError: division by zero
最后执行了……
同样出错了,但是程序处理完错误信息后会继续执行。
因为错误对象就是class,其实我们自己也可以自定义错误用于抛出。
首先,应该定义一个错误的类,选择继承关系,然后用raise关键字抛出实例,创建一个err_raise.py文件:
class FooError(ValueError):
pass
def foo(s):
n = int(s)
if n == 0 :
raise FooError('非法的数值:%s' % s)
return 10 / n foo('')
执行后,如果有错误,我们可以追踪到自己定义的错误:
PS E:\Python3.6.3\workspace> python err_raise.py
Traceback (most recent call last):
File "err_raise.py", line 9, in <module>
foo('')
File "err_raise.py", line 6, in foo
raise FooError('非法的数值:%s' % s)
__main__.FooError: 非法的数值:0
有些时候我们会碰到一些当前代码不适合处理或者不能处理的错误,我可以选择记录下错误之后,在向上抛,这时在except代码块中加入raise语句。raise语句还可以将错误类型转化。
python错误处理—try…catch…finally、调用栈分析的更多相关文章
- Python错误 -- try/except/finally 、调用栈、记录错误、抛出错误
Bug:程序编写有问题造成的错误,称之为Bug. debug:调试 注意:bug是程序本身有问题.有缺陷.系统漏洞 异常:完全无法在程序运行中预测的错误,例如写入文件的时候,磁盘满了,写不进去了 ...
- Android群英传》读书笔记 (4) 第八章 Activity和Activity调用栈分析 + 第九章 系统信息与安全机制 + 第十章 性能优化
第八章 Activity和Activity调用栈分析 1.Activity生命周期理解生命周期就是两张图:第一张图是回字型的生命周期图第二张图是金字塔型的生命周期图 注意点(1)从stopped状态重 ...
- PL/SQL精明的调用栈分析
PL/SQL精明的调用栈分析 原文:http://www.oracle.com/technetwork/issue-archive/2014/14-jan/o14plsql-2045346.html ...
- Android群英传笔记——第八章:Activity与Activity调用栈分析
Android群英传笔记--第八章:Activity与Activity调用栈分析 开篇,我们陈述一下Activity,Activity是整个应用用户交互的核心组件,了解Activity的工作模式,生命 ...
- 第四章 Activity和Activity调用栈分析 系统信息与安全机制 性能优化
1.Activity生命周期理解生命周期就是两张图:第一张图是回字型的生命周期图第二张图是金字塔型的生命周期图 注意点(1)从stopped状态重新回到前台状态的时候会先调用onRestart方法,然 ...
- Android组件内核之Activity调用栈分析(一)
阿里P7Android高级架构进阶视频免费学习请点击:https://space.bilibili.com/474380680 导语 我们陈述一下Activity,Activity是整个应用用户交互的 ...
- C与lua交互--lua调用栈分析(2)
0 预备知识: 至少对Lua手册C API有简单的了解.lua5.3手册中文 1 Lua虚拟机的栈,如图: 假设虚拟机的栈有n个数据: 解释: 两种解释方式: A,栈顶开始, -1 ...-n B, ...
- python 多个装饰器的调用顺序分析
一般情况下,在函数中可以使用一个装饰器,但是有时也会有两个或两个以上的装饰器.多个装饰器装饰的顺序是从里到外(就近原则),而调用的顺序是从外到里(就远原则) 样例: def func1(func): ...
- python错误、调试、测试
1.错误, Python内置的try...except...finally用来处理错误十分方便.出错时,会分析错误信息并定位错误发生的代码位置才是最关键的. 程序也可以主动抛出错误,让调用者来处理相应 ...
随机推荐
- pyhton3 之 time模块实例小结
一.实例1:实现秒表: import time print('按下回车开始计时,按下 Ctrl + C 停止计时.') while True: try: input() # 如果是 python 2. ...
- Spring Boot2 系列教程(二十七)Nginx 极简扫盲入门
上篇文章和大家聊了 Spring Session 实现 Session 共享的问题,有的小伙伴看了后表示对 Nginx 还是很懵,因此有了这篇文章,算是一个 Nginx 扫盲入门吧! 基本介绍 Ngi ...
- (四十四)golang--协程(goroutine)和管道(channel)相结合实例
统计1-8000之间的素数. 整体框架: 说明:有五个协程,三个管道.其中一个协程用于写入数字到intChan管道中,另外四个用于取出intChan管道中的数字并判断是否是素数,然后将素数写入到pri ...
- 【CPLUSOJ】【USACO】【差分约束】排队(layout)
[题目描述] Robin喜欢将他的奶牛们排成一队.假设他有N头奶牛,编号为1至N.这些奶牛按照编号大小排列,并且由于它们都很想早点吃饭,于是就很可能出现多头奶牛挤在同一位置的情况(也就是说,如果我们认 ...
- python字符串删除,列表删除以及字典删除的总结
一:字符串删除 1,字符串本身是不可变的,一个字符串定义以后,对他本身是不能做任何操作的,所以的增删改都是对原字符串拷贝的副本的操作,原来的字符串还是原来的字符串,它本身并没 有变 2,字符串本身是 ...
- 用 python 分析基金!让赚钱赢在起跑线!
你不理财,财不理你!python 也能帮你理财? 效果预览 累计收益率走势图 基本信息结果 如何使用: python3 + 一些第三方库 import requests import pandas i ...
- JSON.parse() 报错和一些解决方法
js 报错 Unexpected end of JSON input,Unexpected token u in JSON at position 0 JSON 通常用于与服务端交换数据. 在接收服务 ...
- 《Dotnet9》系列-开源C# WPF控件库3《HandyControl》强力推荐
大家好,我是Dotnet9小编,一个从事dotnet开发8年+的程序员.我最近开始写dotnet分享文章,希望能让更多人看到dotnet的发展,了解更多dotnet技术,帮助dotnet程序员应用do ...
- 【华为云实战开发】9.如何进行PHP项目的快速搭建并实现CICD?【华为云技术分享】
1 概述 1.1 文章目的 本文主要想为研发PHP项目的企业或个人提供上云指导,通过本文中的示例项目 “workerman-todpole”,为开发者提供包括项目管理,代码托管,代码检查,编译构建,测 ...
- 走近深度学习,认识MoXing:初识华为云ModelArts的王牌利器 — MoXing
[摘要] 本文为MoXing系列文章第一篇,主要介绍什么是MoXing,MoXing API的优势以及MoXing程序的基本结构. MoXing的概念 MoXing是华为云深度学习服务提供的网络模型开 ...