人生苦短,我用python。

一、错误和异常

1、BaseException

BaseException: 所有错误异常的基类

  • KeyboardInterrupt : 用户中断执行
  • SystemExit : 解释器请求推出
  • GeneratorExit : 生成器(generator)发生异常来通知退出
  • Exception : 常规错误的基类

2、Exception

Exception: 常规错误异常的基类

  • StopIteration : 迭代器没有更多的值
  • StandardError : 所有的内建标准异常的基类
  • ArithmeticError : 所有数值计算错误的基类
  • FloatingPointError : 浮点计算错误
  • OverflowError : 数值运算超出最大限制
  • ZeroDivisionError : 除(或取模)零 (所有数据类型)
  • AssertionError : 断言语句失败
  • AttributeError : 对象没有这个属性
  • EOFError : 没有内建输入,到达EOF 标记
  • EnvironmentError : 操作系统错误的基类
  • IOError : 输入/输出操作失败
  • OSError : 操作系统错误
  • WindowsError : 系统调用失败
  • ImportError : 导入模块/对象失败
  • LookupError : 无效数据查询的基类
  • IndexError : 序列中没有此索引(index)
  • KeyError : 映射中没有这个键
  • MemoryError : 内存溢出错误(对于Python 解释器不是致命的)
  • NameError : 未声明/初始化对象 (没有属性)
  • UnboundLocalError : 访问未初始化的本地变量
  • ReferenceError : 弱引用(Weak reference)试图访问已经垃圾回收了的对象
  • RuntimeError : 一般的运行时错误
  • NotImplementedError : 尚未实现的方法
  • SyntaxError : Python 语法错误
  • IndentationError : 缩进错误
  • TabError : Tab 和空格混用
  • SystemError : 一般的解释器系统错误
  • TypeError : 对类型无效的操作
  • ValueError : 传入无效的参数
  • UnicodeError : Unicode 相关的错误
  • UnicodeDecodeError : Unicode 解码时的错误
  • UnicodeEncodeError : Unicode 编码时错误
  • UnicodeTranslateError : Unicode 转换时错误
  • Warning : 警告的基类
  • DeprecationWarning : 关于被弃用的特征的警告
  • FutureWarning : 关于构造将来语义会有改变的警告
  • OverflowWarning : 旧的关于自动提升为长整型(long)的警告
  • PendingDeprecationWarning : 关于特性将会被废弃的警告
  • RuntimeWarning : 可疑的运行时行为(runtime behavior)的警告
  • SyntaxWarning : 可疑的语法的警告
  • UserWarning : 用户代码生成的警告

3、继承关系

错误异常继承关系

二、异常处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
try: #需要监测的代码
...
except exception1: #捕获一个异常
...
except (exception2, exception3): #同时处理多个异常,写在元组里
...
except exception4 as e4: #给异常取别名
...
except: #最后一个except可以忽略异常的名称,它将被当作通配符使用
...
else: #可选的else必须放在所有的except之后,将在try没有发生任何异常时执行
...
finally: #不管try里面有没有发生异常,finally都会执行
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 异常
class MyError(Exception): # 自定义异常
def __init__(self, value):
self.value = value
def __str__(self):
return repr(self.value)

def divide(x,y):
try:
result = x/y
if result == 3:
raise MyError(result) # 抛出自定义异常
except MyError as mE: # 捕获自定义异常
print('My exception occurred, value:', mE.value)
except ZeroDivisionError: # 捕获异常
print('division by zero!')
except:
raise # 向上抛出异常
else: # 没有发生异常时执行
print('result is', result)
finally: # 不管发不发生异常,最后都会执行
print("executing finally clause")

divide(3,1)
divide(2,0)

三、抛出异常

raise语句抛出一个指定的异常。

1
2
3
4
5
try:
raise NameError('HiThere')
except NameError:
print('An exception flew by!')
raise

四、自定义异常

你可以通过创建一个新的exception类来拥有自己的异常。异常应该继承自Exception类,或者直接继承,或者间接继承,例如:

1
2
3
4
5
6
7
8
9
10
>>> class MyError(Exception):
def __init__(self, value):
self.value = value
def __str__(self):
return repr(self.value)

>>> try:
raise MyError(2*2)
except MyError as e:
print('My exception occurred, value:', e.value)

当创建一个模块有可能抛出多种不同的异常时,一种通常的做法是为这个包建立一个基础异常类,然后基于这个基础类为不同的错误情况创建不同的子类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Error(Exception):
"""Base class for exceptions in this module."""
pass

class InputError(Error):
"""Exception raised for errors in the input.

Attributes:
expression -- input expression in which the error occurred
message -- explanation of the error
"""

def __init__(self, expression, message):
self.expression = expression
self.message = message

class TransitionError(Error):
"""Raised when an operation attempts a state transition that's not
allowed.

Attributes:
previous -- state at beginning of transition
next -- attempted new state
message -- explanation of why the specific transition is not allowed
"""

def __init__(self, previous, next, message):
self.previous = previous
self.next = next
self.message = message

五、清理行为

1、定义清理行为

try语句有一个可选的finally子句,它定义了无论在任何情况下都会执行的清理行为:

1
2
3
4
try:
raise KeyboardInterrupt
finally:
print('Goodbye, world!')

2、预定义清理行为

一些对象定义了标准的清理行为,无论系统是否成功的使用了它,一旦不需要它了,那么这个标准的清理行为就会执行。
with语句就可以保证诸如文件之类的对象在使用完之后一定会正确的执行他的清理方法:

1
2
3
with open("myfile.txt") as f:
for line in f:
print(line, end="")

六、调试

1、print()

print()把可能有问题的变量打印出来看看,用print()最大的坏处是将来还得删掉它,想想程序里到处都是print(),运行结果也会包含很多垃圾信息。

2、assert

如果断言失败,assert语句本身就会抛出AssertionError。

1
2
3
4
def foo(s):
n = int(s)
assert n != 0, 'n is zero!'
return 10 / n

程序中如果到处充斥着assert,和print()相比也好不到哪去。不过,启动Python解释器时可以用-O参数来关闭assert
python -O err.py

3、logging

logging不会抛出错误,而且可以输出到文件,推荐使用。
允许指定记录信息的级别:debug、info、warning、error。

1
2
3
4
5
6
7
8
# err.py
import logging #使用前导入包
logging.basicConfig(level=logging.INFO) #配置打印信息级别

s = '0'
n = int(s)
logging.info('n = %d' % n) #记录要打印的信息
print(10 / n)

4、pdb

(1)启动Python的调试器pdb,让程序以单步方式运行:python -m pdb err.py
(2)pdb定位到下一步要执行的代码,输入命令l来查看代码。
(3)输入命令n可以单步执行代码。
(4)任何时候都可以输入命令p 变量名来查看变量。
(5)输入命令q结束调试,退出程序。

5、pdb.set_trace()

只需要import pdb,然后在可能出错的地方放一个pdb.set_trace(),就可以设置一个断点,用命令p查看变量,用命令c继续运行:

1
2
3
4
5
6
7
# err.py
import pdb

s = '0'
n = int(s)
pdb.set_trace() # 运行到这里会自动暂停
print(10 / n)

6、IDE

如果要比较爽地设置断点、单步执行,就需要一个支持调试功能的IDE

持续更新…

最后更新: 2018年12月04日 14:39

原始链接: http://pythonfood.github.io/2017/12/30/python错误异常/

× 多少都行~
打赏二维码