Python中,常见的两种错误:语法错误和异常( syntax errors 和 exceptions )
语法错误,也被称作解析错误。
例如:
>>> while True print 'Hello world'
File "<stdin>", line 1, in ?
while True print 'Hello world'
^
SyntaxError: invalid syntax
异常, 运行期检测到的错误
即使一条语句或表达式在语法上是正确的,当试图执行它时也可能会引发错误。
运行期检测到的错误称为 异常,并且程序不会无条件的崩溃。
try-except
>>> while True:
... try:
... x = int(raw_input("Please enter a number: "))
... break
... except ValueError:
... print "Oops! That was no valid number. Try again..."
一个 try 语句可能包含多个 except 子句,分别指定处理不同的异常。至多只会有一个分支被执行。异常处理程序只会处理对应的 try 子句中发生的异常,在同一个 try 语句中,其他子句中发生的异常则不作处理。一个 except 子句可以在括号中列出多个异常的名字,例如:
... except (RuntimeError, TypeError, NameError):
... pass
最后一个 except 子句可以省略异常名称,以作为通配符使用。你需要慎用此法,因为它会轻易隐藏一个实际的程序错误!可以使用这种方法打印一条错误信息,然后重新抛出异常(允许调用者处理这个异常):
import sys
try:
f = open('myfile.txt')
s = f.readline()
i = int(s.strip())
except IOError as e:
print "I/O error({0}): {1}".format(e.errno, e.strerror)
except ValueError:
print "Could not convert data to an integer."
except:
print "Unexpected error:", sys.exc_info()[0]
raise
try-except-else
else子句,只能出现在所有 except 子句之后。当 try 语句没有抛出异常时,需要执行一些代码,可以使用这个子句。例如
for arg in sys.argv[1:]:
try:
f = open(arg, 'r')
except IOError:
print 'cannot open', arg
else:
print arg, 'has', len(f.readlines()), 'lines'
f.close()
使用 else 子句比在 try 子句中附加代码要好,因为这样可以避免 try … except 意外的截获本来不属于它们保护的那些代码抛出的异常。
抛出异常, raise 语句允许程序员强制抛出一个指定的异常。
例如:
>>> raise NameError('HiThere')
Traceback (most recent call last):
File "<stdin>", line 1, in ?
NameError: HiThere
要抛出的异常由 raise 的唯一参数标识。它必需是一个异常实例或异常类(继承自 Exception 的类)。
如果你需要明确一个异常是否抛出,但不想处理它,raise 语句可以让你很简单的重新抛出该异常:
>>> try:
... raise NameError('HiThere')
... except NameError:
... print 'An exception flew by!'
... raise
...
An exception flew by!
Traceback (most recent call last):
File "<stdin>", line 2, in ?
NameError: HiThere
用户自定义异常
异常类通常应该直接或间接的从 Exception 类派生
例如:
>>> 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
...
My exception occurred, value: 4
>>> raise MyError('oops!')
Traceback (most recent call last):
File "<stdin>", line 1, in ?
__main__.MyError: 'oops!'
try-except-finally
不管有没有发生异常,finally子句 在程序离开 try 后都一定会被执行。
当 try 语句中发生了未被 except 捕获的异常(或者它发生在 except 或 else 子句中),在 finally 子句执行完后它会被重新抛出。
try 语句经由 break,continue 或 return 语句退出也一样会执行 finally 子句。