要么做第一个,要么做最好的一个。

目录

我们在编写程序时,总会不自觉的出现一些错误,比如逻辑错误,语法错误和一些其它的运行时错误等。

逻辑错误: 这种错误不会导致程序崩溃,它不容易被发现,只有在执行结果不是我们预期的时候,才会被发现。

语法错误: 这种错误是不符合语法规定的错误,说白了,就是编译器或者解释器无法理解的代码。出现这种错误时,程序是不能运行的。

其它运行时错误: 这种错误是程序在运行的过程中出现的,一般情况下不会出现,但是极端情况下会出现,是程序编写者考虑不够周全导致的。

在写程序时一定要把所有的情况都考虑到,并且处理掉,不能有侥幸心理(认为某种情况不会出现)。在程序中,只要是有可能出现的情况,那就一定会出现。

程序员也喜欢将这些错误戏称为bug,bug代表软件系统中的漏洞或缺陷,bug需要修正,否则程序是无法正常运行的。重要的软件系统如果出现漏洞,会带来巨大的危害。因此,在软件初步完成后,要进行严格的,全面的测试,否则将漏洞百出。

Python 中提供了一套处理错误的机制,叫做异常。

比较普通的处理错误的方法,是使用if 语句 或断言assert来对各种情况进行判断,从而进行相应的处理。而异常是一种更加高级的处理错误的机制。

1,常见异常

我们来看一些Python 中常见的异常。

SyntaxError 异常

Python 语言有自己的语法格式和规则,如果我们没有遵守这些规则,将会出现异常:

>>> print('abc')- # 右括号后边有一个横线

File "", line 1

print('abc')-

^

SyntaxError: invalid syntax

上尖括号^指出了异常出现的的位置。

NameError 异常

如果我们使用了一个未定义的变量,将会出现该异常:

>>> print(a) # a 变量未定义

Traceback (most recent call last):

File "", line 1, in

NameError: name 'a' is not defined

ZeroDivisionError 异常

进行除法运算时,如果除数为0,将会该异常:

>>> 1 / 0 # 除数为 0

Traceback (most recent call last):

File "", line 1, in

ZeroDivisionError: division by zero

如果程序没有处理异常,在异常出现时,将会崩溃退出,Python 解释器会为你定位到异常出现的位置,有助于快速的解决异常。

2,处理异常

异常需要捕获,从而处理异常。如果在发生异常时,这个异常没有被捕获处理,这个异常将会一层一层的向上抛,直到这个异常被捕获处理,或者程序崩溃。

try except 语句

在Python 中使用try 语句块来捕获异常,在except 语句块中处理异常。

我们一般将有可能出现异常的语句放在try 语句块中,在except 语句块中编写处理异常的措施。

比如,我们有如下代码:

def hello(s):

print('hello %s' % s)

hello('123', 'abc')

其中hello 函数的定义是需要接收一个参数,而在调用时,传递了两个参数,运行此代码将出现如下异常:

Traceback (most recent call last):

File "Test.py", line 8, in

hello('123', 'abc')

TypeError: hello() takes 1 positional argument but 2 were given

代码在遇到异常时,会在异常代码处抛出异常,后边的代码将不会再执行。如果异常代码没有处理,程序将崩溃退出。

我们可以这样处理该异常:

try:

hello('123', 'abc')

except Exception as e:

print(e)

我们将调用语句放在了try 语句块中,这样就可以捕获异常。except 关键字的后边是要捕获的异常的名字,as 后边是捕获到的异常 e。在except 语句块中,我们只是将捕获到的异常打印了出来,运行该代码,结果如下:

hello() takes 1 positional argument but 2 were given

可见错误被打印了出来。我们还可以在打印错误之后,再正确的调用hello 函数:

try:

hello('123', 'abc')

except Exception as e:

print(e)

hello('123')

运行结果如下:

hello() takes 1 positional argument but 2 were given

hello 123

可见,运行到hello('123', 'abc') 时,出现异常,然后代码执行到except 语句块,print(e) 将错误打印出来,又执行了hello('123')。

打印异常是最简单的处理异常的方式,在工作中,我们会将异常信息记录在日志文件中,这样可以将异常记录下来,以便处理异常。

一般在捕获异常时,尽量只在try 语句块中编写有可能发生异常的代码,基本不会发生异常的语句不要写在try 块中,这样可以减少try 块中的代码量,有助于定位问题。

except 语句

except 关键字后边可以跟一个异常名字,也可以跟一组异常名字,一组异常时,将多个异常的名字写在一个元组中,语法如下:

except (Error1, Error2...):

pass

一个try 语句中,也可以包含多个except 语句块,语法如下:

try:

# 代码块

except Error1 as e:

# 处理 Error1

except Error2 as e:

# 处理 Error2

.

.

.

except:

e = sys.exc_info()[0])

pass

多个except 语句块时,Python 解释器会从上到下依次判断异常的类型,直到符合某个异常时,会执行对应的语句块中的代码,在该except 块之后的except 块将被忽略。

其中,最后一个except 块可以省略异常的名字,这种格式可以匹配任意的异常,在该块中,可以使用sys.exc_info()[0] 来获取异常。

在有多个except 语句块时,要注意,前边的异常的范围应该小于等于后边的异常的范围,否则,后边的except 块将没有意义。

else 语句

Python 中,try... except... 之后还可以有一个else语句块,except 语句块是在遇到异常时执行的,else 语句块是在没有遇到异常时执行的。

发生异常时,示例:

try:

hello('123', 'abc')

except Exception as e:

print('发生异常')

print(e)

else:

print('没有发生异常')

上面的代码中,执行到hello('123', 'abc') 时会发生异常,然后会进入到except 语句块,else 语句不会被执行,执行结果如下:

发生异常

hello() takes 1 positional argument but 2 were given

没有发生异常时,示例:

try:

hello('123')

except Exception as e:

print('发生异常')

print(e)

else:

print('没有发生异常')

上面代码中的try 语句块不会发生异常,那么except 语句就不会执行,else 语句会执行,结果如下:

hello 123

没有发生异常

注意:

else 语句的使用频率并不高。

finally 语句

finally 语句块无论是否异常都会被执行,该语句块经常用在需要关闭系统资源的情况下。

没有发生异常时,示例如下:

try:

hello('123')

except Exception as e:

print('发生异常')

print(e)

else:

print('没有发生异常')

finally:

print('执行了 finally 语句块')

上面代码中,try 语句块没有发生异常,else 与 finally 都被执行,except 语句块没有执行。运行结果如下:

hello 123

没有发生异常

执行了 finally 语句块

发生异常时,示例如下:

try:

hello('123', 'abc')

except Exception as e:

print('发生异常')

print(e)

else:

print('没有发生异常')

finally:

print('执行了 finally 语句块')

上面代码中,try 语句块发生异常,except 与 finally 都被执行,else 语句块没有执行。运行结果如下:

发生异常

hello() takes 1 positional argument but 2 were given

执行了 finally 语句块

注意:

else 语句块与finally 语句块可以同时存在,也可以同时不存在,也可以一个存在一个不存在,互不影响。

3,抛出异常

raise 异常

如果你捕获了一个异常,却不想彻底解决这个异常,而想将该异常向上层抛出,可以使用raise 关键字。

raise 用于抛出异常,其后可以跟一个异常对象,或者什么也不跟。

raise 后跟一个异常对象:

raise Exception('这里发生了错误')

raise 后什么也不跟:

try:

hello('123', 'abc')

except Exception as e:

print('发生异常')

raise

Python 解释器会记录最后一个发生的异常,raise 会将最后一个异常抛出。上面代码中的raise 相当于raise e。

assert 断言

assert 语句称为断言,就是判断某个表达式是否为真:

表达式为True 时,正常通过

表达式为False 时,抛出AssertionError 异常

示例如下:

表达式1 == 1为True,没有反应:

>>> assert 1 == 1

表达式1 == 0为False,抛出异常:

>>> assert 1 == 0

Traceback (most recent call last):

File "", line 1, in

AssertionError

4,Python 异常层次结构

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

可参考这里:

https://docs.python.org/3/library/exceptions.html#exception-hierarchy

这些都是内建异常,BaseException 是所有异常的父类,我们使用最多的是Exception 及其子类。可以使用help(类名)来查看每个类的详情。

5,自定义异常

有时候,我们需要定义自己的异常类,来满足自己的需求。

我们已经知道,Python 异常类有自己的层次结构,所有的类都直接或者间接继承了BaseException。因此,用户自定义的异常类,也需要满足这种层次结构。

一般情况下,自定义异常需要继承Exception 类。如下:

class MyError(Exception):

pass

MyError 类的使用方式,跟内建异常类的使用方式一样。你可以根据自己的需要,为MyError 类编写相应的构造方法,和其它类方法。

如果没有为MyError 编写构造方法,那么MyError 就继承了Exception 的构造方法。

6,调试错误

程序编写完成后不一定是正确的,当发现有错误时,就需要定位错误的位置。

最普遍,最简单的调错的方法就是打印某个变量,通过输出变量的值,来查看其是否是你想要的结果。

另一种比较高效,有力的调试代码的方式是单步调试,即是通过设置断点,深入到代码内部,一步一步的跟踪查看代码的执行结果是否正确,从而达到修正代码的目的。

在C 语言中有一个非常著名的工具叫做gdb,这是一款强大的调试工具。Python 中也有类似的一款工具叫做pdb,它使用起来要比gdb 简单许多。

在Python 中,pdb 是一个模块,所以,在使用之前要先使用import pdb 将该模块引入。然后,在需要调试代码的地方,使用pdb.set_trace() 方法来设置断点,在代码执行到此处时,Python 解释器就会从此处开始让你调式代码。

如下代码,文件名为Test.py:

#! /usr/bin/env python3

# 引入 pdb 模块

import pdb

def hello(s):

print('hello %s' % s)

# 设置断点

pdb.set_trace()

hello('python')

hello('java')

我们使用python3 来运行该程序,如下:

$ python3 Test.py

> ~/Test.py(12)()

-> hello('python')

(Pdb)

可以看到代码在hello('python')之前暂停并进入断点,控制台显示出(Pdb),我们可以在这个后面输入Python 代码或者pdb 支持的命令。

pdb 常用命令如下:

n:进行下一步代码,即单步执行

c:代码执行到下一个断点处,如果没有下一个断点,则执行到程序结束

s:在遇到函数时,使用s 命令,可以进入函数内部

l:列出当前语句周围的10行代码

p:用于输出变量的值,相当于print 函数

(完。)

推荐阅读:

欢迎关注作者公众号,获取更多技术干货。

python编写异常处理_Python 简明教程 --- 23,Python 异常处理相关推荐

  1. python 三引号_Python 简明教程 --- 4,Python 变量与基本数据类型

    微信公众号:码农充电站pro 个人主页:https://codeshellme.github.io 任何一个人都会写出能够让机器理解的代码,只有好的程序员才能写出人类可以理解的代码. -- Marti ...

  2. python sorted下标_Python学习教程(Python学习路线):第七天-字符串和常用数据结构

    Python学习教程(Python学习路线):字符串和常用数据结构 使用字符串 第二次世界大战促使了现代电子计算机的诞生,当初的想法很简单,就是用计算机来计算导弹的弹道,因此在计算机刚刚诞生的那个年代 ...

  3. python 优雅退出_Python学习教程:Python 使用 backoff 更优雅的实现轮询

    我们经常在开发中会遇到这样一种场景,即轮循操作.今天介绍一个Python库,用于更方便的达到轮循的效果--backoff. Python学习教程:Python 使用 backoff 更优雅的实现轮询 ...

  4. python画四边形_python绘图教程-用python来绘制出四边形

    原标题:python绘图教程-用python来绘制出四边形 python的应用有很多,其中还可以用python来绘制四边形,下面羽忆教程网为您分享如何用python来绘制四边形的详细步骤. pytho ...

  5. python 元组长度_Python 简明教程 ---11,Python 元组

    微信公众号:码农充电站pro 软件工程的目标是控制复杂度,而不是增加复杂性. -- Dr. Pamela Zave 目录 我们在上一节介绍了Python 列表list 数据结构,本节来介绍一下元组tu ...

  6. python dict下标_Python基础教程:python的数据类型

    python基础之五大标准数据类型 学习一门语言,往往都是从Hello World开始. 但是笔者认为,在一个黑框框中输出一个"你好,世界"并没有什么了不起,要看透事物的本质,熟悉 ...

  7. python两层循环 循环完整体一个_Python学习教程(Python学习路线):Python编写循环的两个建议...

    原标题:Python学习教程(Python学习路线):Python编写循环的两个建议 Python学习教程(Python学习路线):给大家总结了两个Python编写循环的建议 循环是一种常用的程序控制 ...

  8. 【Python】【进阶篇】十二、Python爬虫的Xpath简明教程(十分钟入门)

    目录 十二.Python爬虫的Xpath简明教程(十分钟入门) 12.1 Xpath表达式 12.2 Xpath节点 12.3 节点关系 12.4 Xpath基本语法 12.4.1 基本语法使用 12 ...

  9. Python re(正则表达式)简明教程

    Python re(正则表达式)简明教程(Python3) 举个栗子 常用函数举例 按字母顺序查询模块

最新文章

  1. petaPar培训文档
  2. vb子程序未定义怎么改怎么办_提示子程序或函数未定义怎么修改。。。
  3. 编程中python怎么读-python之文件读写
  4. 《云计算》学习笔记1
  5. linux 安装库 编译提示-lcrypto 无法链接,缺少 crypto 库
  6. CodeForces - 1521D Nastia Plays with a Tree(树上最小路径覆盖)
  7. 中国剧本推理市场洞察2021
  8. 【CSS】【7】CSS的盒子模型
  9. 同事乱用分页 MySQL 卡爆,我真是醉了...
  10. 投射电子显微镜(TEM)
  11. puts与fputs的区别
  12. 空间句法(二)——Axwoman 6.0
  13. 服务器常用语言,计算机常用词汇--语言及服务器篇
  14. js实现全屏和退出全屏功能
  15. 工业控制计算机固态硬盘,工业控制电脑ssd固态硬盘怎么正确使用?
  16. java支持wingdings吗,[转]往JRE里添加新字体
  17. 云计算在商业智能运用中,主要存在哪些难点?
  18. Win7双网卡共享上网
  19. 「切图仔日常」浅谈加载动画两板斧
  20. 进阶篇:如何优化网站提升访问速度

热门文章

  1. php 编程祝新年快乐_AnyCodes:免费的在线编程神器
  2. dsp指令ixh_第一章 DSP入门教程(非常经典).pdf
  3. Spring入门详细教程(三)
  4. 机器人简化图画手绘图_床上用的扫地机器人,彻底清除细菌,不再担心酒店卫生问题...
  5. java compareto方法怎么排序的_深入理解Java中Comparable和Comparator排序
  6. jdbc封装mysql_用Java手动封装JDBC连接池(一)
  7. 企业研发人员配备比例_企业管理人员合理配置比例
  8. python如何查询数据库_Python数据库操作手册-数据库专栏,SQL Server
  9. 【深度学习入门到精通系列】Mean Iou
  10. python【数据结构与算法】多字段条件排序