错误处理
一个 try 语句可能包含多个except子句,分别来处理不同的特定的异常。
except (RuntimeError, TypeError, NameError): 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
try except 语句还有一个可选的else子句,如果使用这个子句,那么必须放在所有的except子句之后。这个子句将在try子句没有发生任何异常的时候执行。使用 else 子句比把所有的语句都放在 try 子句里面要好,这样可以避免一些意想不到的、而except又没有捕获的异常
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()
用户自定义异常
>>>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!'
-
记录错误
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('0') except Exception as e: logging.exception(e) main() print('END')
同样是出错,但程序打印完错误信息后会继续执行,并正常退出。通过配置,logging还可以把错误记录到日志文件里,方便事后排查
ERROR:root:division by zero Traceback (most recent call last): File "D:/PycharmProjects/tes/ex.py", line 16, in main bar('0') File "D:/PycharmProjects/tes/ex.py", line 12, in bar return foo(s) * 2 File "D:/PycharmProjects/tes/ex.py", line 9, in foo return 10 / int(s) ZeroDivisionError: division by zero END
-
抛出错误
因为错误是class,捕获一个错误就是捕获到该class的一个实例。因此,错误并不是凭空产生的,而是有意创建并抛出的。Python的内置函数会抛出很多类型的错误,我们自己编写的函数也可以抛出错误。
如果要抛出错误,首先根据需要,可以定义一个错误的class,选择好继承关系,然后,用raise语句抛出一个错误的实例
class FooError(ValueError): pass def Foo(s): n = int(s) if n == 0: raise FooError('invalid value: %s' % s) return 10 / n Foo('0')
执行,可以最后跟踪到我们自己定义的错误
Traceback (most recent call last): File "err_throw.py", line 11, in <module> foo('0') File "err_throw.py", line 8, in foo raise FooError('invalid value: %s' % s) __main__.FooError: invalid value: 0
调试
-
断言
def foo(s): n = int(s) assert n != 0, 'n is zero!' return 10 / n def main(): foo('0')
-
logging
logging不会抛出错误,而且可以输出到文件。
import logging s = '0' n = int(s) logging.info('n = %d' % n) print(10 / n)
logging.info()就可以输出一段文本。运行,发现除了ZeroDivisionError,没有任何信息,在import logging之后添加一行配置再试试。
import logging logging.basicConfig(level = logging.INFO)