ThinkSSL🔒 一键申购 5分钟快速签发 30天无理由退款 购买更放心 广告
# 错误处理 [TOC] ## 捕获异常 所有的错误类型都继承自BaseException,所以在使用except时需要注意的是,**它不但捕获该类型的错误,还把其子类也“一网打尽”** [常见的错误类型和继承关系][1] ``` # 有可能用到的 BaseException +-- Exception +-- StopIteration +-- AttributeError +-- BufferError +-- LookupError | +-- IndexError | +-- KeyError +-- MemoryError +-- NameError | +-- UnboundLocalError +-- OSError | +-- FileExistsError | +-- FileNotFoundError | +-- TimeoutError +-- ReferenceError +-- RuntimeError | +-- NotImplementedError | +-- RecursionError +-- SyntaxError | +-- IndentationError | +-- TabError +-- SystemError +-- TypeError +-- ValueError ``` ```python try: print('try...') r = 10 / int('a') # r = 10 / 2 print('result:', r) except ValueError as e: print('ValueError:', e) # ValueError: invalid literal for int() with base 10: 'a' except ZeroDivisionError as e: print('ZeroDivisionError:', e) # 不同的错误类型接收不同的错误,父类也会抛出子类的错误 else: print('no error!') # 没有错误就就执行else finally: print('finally...') print('END') ``` ## 记录错误 Python内置的logging模块可以非常容易地记录错误信息,可以设置日志格式,级别,处理器(保存日志到文件,数据库,缓存) ```python #coding:utf-8 import logging # 配置了日志输出文件,格式,时间 logging.basicConfig(filename='log1.log', format='%(asctime)s -%(name)s-%(levelname)s-%(module)s:%(message)s', datefmt='%Y-%m-%d %H:%M:%S %p', level=logging.DEBUG) while True: option = input("input a digit:") if option.isdigit(): print("hehe",option) logging.info('option correct') else: logging.error("Must input a digit!") # 日志级别 # logging.debug('有bug') # logging.info('有新的信息') # logging.warning('警告信息') # logging.error('错误信息') # logging.critical('紧急错误信息') # logging.log(10,'log') #coding:utf-8 #coding:utf-8 import logging # 获取日志实例 logger = logging.getLogger("simple_example") logger.setLevel(logging.DEBUG) #输出到屏幕 ch = logging.StreamHandler() ch.setLevel(logging.WARNING) #输出到文件 fh = logging.FileHandler("log2.log") fh.setLevel(logging.INFO) #设置日志格式 fomatter = logging.Formatter('%(asctime)s -%(name)s-%(levelname)s-%(module)s:%(message)s') ch.setFormatter(fomatter) fh.setFormatter(fomatter) logger.addHandler(ch) logger.addHandler(fh) #输出日志 logger.debug("debug message") logger.info("info message") logger.warning("warning message") logger.error("error message") logger.critical("critical message") ``` 用到时具体查看相关文章 [Python中的logging模块][2] ## 抛出错误 ### raise ```python # 可以自定义错误类,但如果可以选择Python已有的内置的错误类型(比如ValueError,TypeError),尽量使用Python内置的错误类型。 class FooError(ValueError): pass def foo(s): n = int(s) if n==0: raise FooError('invalid value: %s' % s) return 10 / n def bar(): try: foo('0') except ValueError as e: # invalid value: 0 print(e) bar() ``` ### reise from ```python class FooError(ValueError): def __init__(self, msg, country_code): self.msg = msg self.country_code = country_code def foo(s): n = int(s) if n==0: # 由于内置的错误类可以传入任意的参数 raise FooError('invalid value: %s' % s,22) from ValueError return 10 / n def bar(): try: foo('0') except FooError as exc: # 语义化接管了 print(exc.country_code) bar() ``` ## 断言 凡是用print()来辅助查看的地方,都可以用断言(assert)来替代。 ```python def foo(s): n = int(s) assert n != 0, 'n is zero!' # 表达式n != 0应该是True,否则,抛出错误AssertionError return 10 / n try: foo(0) except Exception as e: # <AssertionError> : n is zero! print('<%s> : %s' % (e.__class__.__name__,str(e))) # python -O err.py 启动Python解释器时可以用-O参数来关闭assert ``` ## [单元测试] [3] ## [文档测试] [4] [1]: https://docs.python.org/3/library/exceptions.html#exception-hierarchy [2]: http://python.jobbole.com/86887/ [3]: https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/00143191629979802b566644aa84656b50cd484ec4a7838000