1.错误处理
try:
print('try...')
r = 10 / int('2')
print('result:', r)
except ValueError as e:
print('ValueError:', e)
except ZeroDivisionError: ##最后一个except子句可以忽略异常的名称,它将被当作通配符使用
print('ZeroDivisionError:', e)
else:
print('no error!')
finally:
print('finally...')
print('END')
如果一个异常没有与任何的 excep 匹配,那么这个异常将会传递给上层的 try 中。 一个except子句可以同时处理多个异常,这些异常将被放在一个括号里成为一个元组,例如: except (RuntimeError, TypeError, NameError): pass 如果没有错误发生,可以在 Python所有的错误都是从 常见的错误类型和继承关系看这里:https://docs./3/library/exceptions.html#exception-hierarchy 捕获错误,可以多层调用。 出错的时候,一定要分析错误的调用栈信息,才能定位错误的位置。 Python内置的 # 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') 同样是出错,但程序打印完错误信息后会继续执行,并正常退出。
如果要抛出错误,首先根据需要,可以定义一个错误的class,选择好继承关系,然后,用 # err_raise.py class FooError(ValueError): pass def foo(s): n = int(s) if n==0: raise FooError('invalid value: %s' % s) return 10 / n foo('0') 只有在必要的时候才定义我们自己的错误类型。如果可以选择Python已有的内置的错误类型(比如
# err_reraise.py def foo(s): n = int(s) if n==0: raise ValueError('invalid value: %s' % s) return 10 / n def bar(): try: foo('0') except ValueError as e: print('ValueError!') raise bar()
raise 唯一的一个参数指定了要被抛出的异常。它必须是一个异常的实例或者是异常的类(也就是 Exception 的子类)。 在 try: 10 / 0 except ZeroDivisionError: raise ValueError('input error!')
2.调试 1.用 2.凡是用 def foo(s): n = int(s) assert n != 0, 'n is zero!' return 10 / n def main(): foo('0')
如果断言失败, $ python err.py Traceback (most recent call last): ... AssertionError: n is zero! 启动Python解释器时可以用
import logging logging.basicConfig(level=logging.INFO) s = '0' n = int(s) logging.info('n = %d' % n) print(10 / n) 它允许你指定记录信息的级别,有
4.启动Python的调试器pdb。
# err.py import pdb s = '0' n = int(s) pdb.set_trace() # 运行到这里会自动暂停 print(10 / n) 运行代码,程序会自动在 Pycharm的调试程序:https://blog.csdn.net/s740556472/article/details/90054266
3.单元测试单元测试是用来对一个模块、一个函数或者一个类来进行正确性检验的测试工作。 需要引入Python自带的 用到再细查。大体是看懂了。一定要做单元测试。减少测试人员的工作量,也减少很多不必要的错误。 单元测试的测试用例要覆盖常用的输入组合、边界条件和异常。 # -*- coding: utf-8 -*- import unittest class Student(object): def __init__(self, name, score): self.name = name self.score = score def get_grade(self): # if self.score < 0 or self.score > 100: # raise ValueError('ValueError') if self.score >= 60 and self.score < 80: return 'B' elif self.score >= 80 and self.score <= 100: return 'A' elif self.score >= 0 and self.score < 60: return 'C' else: raise ValueError("wrong key") class TestStudent(unittest.TestCase): def test_80_to_100(self): s1 = Student('Bart', 80) s2 = Student('Lisa', 100) self.assertEqual(s1.get_grade(), 'A') self.assertEqual(s2.get_grade(), 'A') def test_60_to_80(self): s1 = Student('Bart', 60) s2 = Student('Lisa', 79) self.assertEqual(s1.get_grade(), 'B') self.assertEqual(s2.get_grade(), 'B') def test_0_to_60(self): s1 = Student('Bart', 0) s2 = Student('Lisa', 59) self.assertEqual(s1.get_grade(), 'C') self.assertEqual(s2.get_grade(), 'C') def test_invalid(self): s1 = Student('Bart', -1) s2 = Student('Lisa', 101) with self.assertRaises(ValueError): s1.get_grade() with self.assertRaises(ValueError): s2.get_grade() if __name__ == '__main__': unittest.main()
4.文档测试# -*- coding: utf-8 -*- def fact(n): ''' Calculate 1*2*...*n >>> fact(1) 1 >>> fact(10) 3628800 >>> fact(-1) Traceback (most recent call last): File "C:\python\lib\doctest.py", line 1329, in __run compileflags, 1), test.globs) File "<doctest __main__.fact[2]>", line 1, in <module> fact(-1) File "C:/Workspace/Document/Private/Code/python/tutorial/study.py", line 917, in fact raise ValueError() ValueError ''' if n < 1: raise ValueError() if n == 1: return 1 return n * fact(n - 1) if __name__ == '__main__': import doctest doctest.testmod() Python内置的“文档测试”(doctest)模块可以直接提取注释中的代码并执行测试。 doctest严格按照Python交互式命令行的输入和输出来判断测试结果是否正确。只有测试异常的时候,可以用 当模块正常导入时,doctest不会被执行。只有在命令行直接运行时,才执行doctest。所以,不必担心doctest会在非测试环境下执行。
参考自:廖老师的python3和菜鸟 |
|