- try语句工作方式
a、首先,执行 try 子句(关键字 try 和关键字 except 之间的语句)
b、如果没有异常发生,忽略 except子句 ,try 子句执行结束
c、如果在执行 try 子句的过程中发生了异常,那么 try 子句余下的部分将被忽略。如果异常的类型和 except 之后的名称相符,那么对应的 except 子句将被执行。最后执行 try 语句之后的代码
d、如果一个异常没有任何 except 匹配,那么这个异常将会传递给上层的 try中
e、一个 try 语句能包含多个 except 子句,分别来处理不同的特定的异常,最多只有一个分支被执行,处理程序将只针对对应的 try 子句中的异常进行处理,而不是其他的 try的处理程序中的异常
f、一个 except 子句可以同时处理多个异常,这些异常将被放在一个括号里成为一个元祖,例如
except (RuntimeError, TypeError, NameError):
pass
1
except (RuntimeError, TypeError, NameError):
2
pass
最后一个 except 子句可以忽略异常的名称,它将被当作通配符使用,你可以使用这种方法答应你一个错误信息,然后在把异常抛出
import sys
try:
f = open('myfile.txt')
s = f.readline()
i = int(s.strip())
except OSError as err:
print("OS error: {0}".format(err))
except ValueError:
print("Could not convert data to an integer.")
except:
print("Unexpected error:", sys.exc_info()[0])
raise
13
1
import sys
2
3
try:
4
f = open('myfile.txt')
5
s = f.readline()
6
i = int(s.strip())
7
except OSError as err:
8
print("OS error: {0}".format(err))
9
except ValueError:
10
print("Could not convert data to an integer.")
11
except:
12
print("Unexpected error:", sys.exc_info()[0])
13
raise
- try except 与 else 子句
a、使用这个子句,必须放在所有的 except 子句之后,这个子句将在 try 子句没有发生任何异常的时候执行
b、使用 else子句把所有的语句,都放在try 子句里面要好,这样可以避免一些意想不到的、而 except 又没有捕获的异常
import sys
for arg in sys.argv[1:]:
try:
f = open(arg, 'r')
except IOError:
print('cannot open', arg)
else: #必须放在所有 except之后,try子句中没有发生任何异常的时候执行
print(arg, 'has', len(f.readlines()), 'lines')
f.close()
10
1
import sys
2
3
for arg in sys.argv[1:]:
4
try:
5
f = open(arg, 'r')
6
except IOError:
7
print('cannot open', arg)
8
else: #必须放在所有 except之后,try子句中没有发生任何异常的时候执行
9
print(arg, 'has', len(f.readlines()), 'lines')
10
f.close()
异常处理并不仅仅处理哪些直接发生在 try 子句中的异常,而且还能处理子句中调用的函数(甚至间接调用的函数)里抛出的异常
def this_fails():
x = 1 / 0
try:
this_fails()
except ZeroDivisionError as err: #如果想让程序继续运行,但是又因为某种原因想记录下错误,可以使用这种 as xxx,然后在 except中print出来
print('Handling run-time error:', err)
Handling run-time error: int division or modulo by zero
出来
x
1
def this_fails():
2
x = 1 / 0
3
4
try:
5
this_fails()
6
except ZeroDivisionError as err: #如果想让程序继续运行,但是又因为某种原因想记录下错误,可以使用这种 as xxx,然后在 except中print出来
7
print('Handling run-time error:', err)
8
9
Handling run-time error: int division or modulo by zero
- 抛出异常
a、Python 使用 raise 语句抛出一个指定的异常
b、raise 唯一的一个参数指定了要抛出的异常,它必须是一个异常的实例或者异常的类(也就是 Exception的子类)
c、如果你只想知道是否抛出一个异常,并不想去处理它,那么一个简单的 raise 语句就可以再次把它抛出
try:
raise NameError('HiThere')
except NameError:
print('An exception flew by!')
raise
x
8
1
try:
2
raise NameError('HiThere')
3
except NameError:
4
print('An exception flew by!')
5
raise
- 用户自定义异常
a、你可以通过创建一个新的 exception 来拥有自己的异常,异常应该继承自 Exception 类,或者直接继承,或者间接继承,
b、当创建一个模块有可能抛出多种不同的异常时,一种通常的做法是为这个包建立一个基础异常类,然后基于这个基础类为不同的错误情况创建不同的子类
class Error(Exception): #继承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
x
1
class Error(Exception): #继承Exception
2
"""Base class for exceptions in this module."""
3
pass
4
5
class InputError(Error):
6
"""Exception raised for errors in the input.
7
8
Attributes:
9
expression -- input expression in which the error occurred
10
message -- explanation of the error
11
"""
12
13
def __init__(self, expression, message):
14
self.expression = expression
15
self.message = message
16
17
class TransitionError(Error):
18
"""Raised when an operation attempts a state transition that's not
19
allowed.
20
21
Attributes:
22
previous -- state at beginning of transition
23
next -- attempted new state
24
message -- explanation of why the specific transition is not allowed
25
"""
26
27
def __init__(self, previous, next, message):
28
self.previous = previous
29
self.next = next
30
self.message = message
- finally
try:
raise KeyboardInterrupt
finally:
print('Goodbye, world!') #不管有没有发生异常,finally语句都会被执行
Goodbye, world!
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
KeyboardInterrupt
x
1
try:
2
raise KeyboardInterrupt
3
finally:
4
print('Goodbye, world!') #不管有没有发生异常,finally语句都会被执行
5
6
Goodbye, world!
7
Traceback (most recent call last):
8
File "<stdin>", line 2, in <module>
9
KeyboardInterrupt
def divide(x,y):
try:
result = x/y
except ZeroDivisionError: #try发生该类异常则执行该语句,执行完成后在执行 try中异常后的语句
print ("division by zero!")
raise
else: #try中无异常输出
print ("result is ",result)
finally: #无论如何都会执行
print ("exxecuting finally clause")
divide(2,1)
#输出
result is 2.0
executing finally clause
divide(2.0)
#输出
division by zero!
executing finally clause
divide("2","1")
#输出
executing finally clause
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 3, in divide
TypeError: unsupported operand type(s) for /: 'str' and 'str'
x
1
def divide(x,y):
2
try:
3
result = x/y
4
except ZeroDivisionError: #try发生该类异常则执行该语句,执行完成后在执行 try中异常后的语句
5
print ("division by zero!")
6
raise
7
else: #try中无异常输出
8
print ("result is ",result)
9
10
finally: #无论如何都会执行
11
print ("exxecuting finally clause")
12
13
divide(2,1)
14
#输出
15
result is 2.0
16
executing finally clause
17
18
divide(2.0)
19
#输出
20
division by zero!
21
executing finally clause
22
23
divide("2","1")
24
#输出
25
executing finally clause
26
Traceback (most recent call last):
27
File "<stdin>", line 1, in ?
28
File "<stdin>", line 3, in divide
29
TypeError: unsupported operand type(s) for /: 'str' and 'str'
- 预定义的清理行为
一些对象定义了标准的清理行为,无论系统是否成功的使用了它,一旦不需要它了,那么这个标准的清理行为就会执行,这面这个例子展示了尝试打开一个文件,然后把内容打印到屏幕上
for line in open("myfile.txt"):
print(line, end="")
1
for line in open("myfile.txt"):
2
print(line, end="")
以上这段代码的问题是,当执行完毕后,文件会保持打开状态,并没有被关闭。
关键词 with 语句就可以保证诸如文件之类的对象在使用完滞后一定会正确的执行他的清理方法:
with open("myfile.txt") as f:
for line in f:
print(line, end="")
1
with open("myfile.txt") as f:
2
for line in f:
3
print(line, end="")
- 一些内建异常
类名 | 描述 |
Exception | 所有异常的基类 |
AttributeError | 特性引用或赋值失败时引发 |
IOError | 试图打开不存在文件(包括其他情况)时引发 |
IndexError | 在使用序列中不存在的索引时引发 |
KeyError | 在使用映射中不存在的键时引发 |
NameError | 在找不到名字(变量)时引发 |
SyntaxError | 在代码为错误形式时引发 |
TypeError | 在内建操作或者函数应用于错误类型的对象时引发 |
ValueError | 在内建操作或者函数应用于正确类型的对象,但是该对象使用不适合的值时引发 |
ZeroDivisionError | 在除法或者模除操作中的第二个参数为0时引发 |