辨别Exception和Syntax Error

在写Python程序的时候常常会报错,报错通常有以下两种状况:

  1. 语法错误(Syntax Error): 局部语法错误属于异样
  2. 异样(Exception)

语法错误

语法错误也称为解析谬误,是最常遇到的一种谬误

In [1]: while True print('Hello!')  File "<ipython-input-1-5c66e4fd0ae9>", line 1    while True print('Hello!')                   ^SyntaxError: invalid syntax

当代码不合乎Python语法的时候就会抛出SyntaxError。

异样

Python用异样对象来示意异常情况。遇到谬误后,会引发异样。如果异样没有解决或捕获,程序就会用traceback终止程序的执行,如果是在多线程程序中,则会终止以后线程的执行。

In [2]: 1/0---------------------------------------------------------------------------ZeroDivisionError                         Traceback (most recent call last)<ipython-input-2-05c9758a9c21> in <module>()----> 1 1/0ZeroDivisionError: division by zero

除以0时,就会抛出ZeroDivisionError异样(ZeroDivisionError类的一个实例)。

<!--more-->

异样层次结构

Python 3.5.2中内置异样的类层次结构如下:参考规范库

BaseException  # 所有异样的基类 +-- SystemExit  # 程序退出/终止 +-- KeyboardInterrupt  # 由键盘中断(通常为Ctrl+C) 生成 +-- GeneratorExit  # 由生成器.close()办法引发 +-- Exception  # 所有非退出异样的基类      +-- StopIteration  # 进行迭代谬误      +-- StopAsyncIteration  # 进行异步迭代谬误      +-- ArithmeticError  # 算数异样的基类      |    +-- FloatingPointError  # 浮点操作异样      |    +-- OverflowError  # 溢出导致的异样      |    +-- ZeroDivisionError  # 对0进行除或取模操作导致的异样      +-- AssertionError  # 由assert语句引发      +-- AttributeError  # 当属性名称有效时引发      +-- BufferError  # 缓冲区谬误引发      +-- EOFError  # 达到文件结尾时引发      +-- ImportError  # import语句失败      +-- LookupError  # 索引和键谬误      |    +-- IndexError  # 超出序列索引的范畴      |    +-- KeyError  # 键不存在      +-- MemoryError  # 内存不足      +-- NameError  # 无奈找到部分或全局名称      |    +-- UnboundLocalError  # 未绑定的局部变量      +-- OSError  # 操作系统谬误      |    +-- BlockingIOError  # IO阻塞      |    +-- ChildProcessError  # 子过程      |    +-- ConnectionError  # 连贯谬误      |    |    +-- BrokenPipeError  # 管道断开      |    |    +-- ConnectionAbortedError  # 连贯停止      |    |    +-- ConnectionRefusedError  # 连贯回绝      |    |    +-- ConnectionResetError  # 连贯重置      |    +-- FileExistsError # 文件已存在      |    +-- FileNotFoundError  # 文件不存在      |    +-- InterruptedError  # 中断谬误      |    +-- IsADirectoryError  # 目录谬误      |    +-- NotADirectoryError  # 非目录谬误      |    +-- PermissionError  # 权限谬误      |    +-- ProcessLookupError  # 过程查找谬误      |    +-- TimeoutError  # 超时谬误      +-- ReferenceError  # 销毁被援用对象后依然应用援用      +-- RuntimeError  # 运行时谬误      |    +-- NotImplementedError  # 没有实现的个性      |    +-- RecursionError  # 递归谬误      +-- SyntaxError  # 语法错误      |    +-- IndentationError  # 缩进谬误      |         +-- TabError  # 应用不统一的制表符      +-- SystemError  # 解释器中的非致命零碎谬误      +-- TypeError  # 给操作传递了谬误的类型      +-- ValueError  # 有效类型      |    +-- UnicodeError  # Unicode谬误      |         +-- UnicodeDecodeError  # Unicode解码谬误      |         +-- UnicodeEncodeError  # Unicode编码谬误      |         +-- UnicodeTranslateError  # Unicode转换谬误      +-- Warning  # 正告的基类           +-- DeprecationWarning  # 对于被弃用的特色的正告           +-- PendingDeprecationWarning  # 对于个性将会被废除的正告           +-- RuntimeWarning  # 可疑的运行时行为的正告           +-- SyntaxWarning  # 可疑的语法的正告           +-- UserWarning  # 用户代码生成的正告           +-- FutureWarning  # 对于结构未来语义会有扭转的正告           +-- ImportWarning  # import语句的正告           +-- UnicodeWarning  # Unicode正告           +-- BytesWarning  # Bytes正告           +-- ResourceWarning  # 资源正告
  • 所有异样的基类都是BaseException
  • 除SystemExit,KeyboardInterrupt,GeneratorExit三种异样外都继承自Exception

捕捉异样

捕捉异样能够应用try/except语句。try/except语句用来检测try语句块中的谬误,从而让except语句捕捉异样信息并解决。

try/except

根底语法

try:    <语句>except <name>:    <语句>          #如果在try局部引发了名为'name'的异样,则执行这段代码

示例

In [3]: try:   ...:     x = int(input("Please enter a number: "))   ...: except ValueError:   ...:     print("No valid number.")   ...:     Please enter a number: asdNo valid number.

多个except

In [4]: import sysIn [5]: try:   ...:     f = open('file.txt')  # 文件不存在的时候就会抛出FileNotFoundError异样   ...:     s = f.readline()   ...:     i = int(s.strip())   ...: except OSError:  # FileNotFoundError异样的下层异样   ...:     print('OS error.')   ...: except ValueError:   ...:     print('Could not convert data to integer.')   ...: except Exception:   ...:     print('Exception.')   ...: except:  # 不加具体异样类型时,会捕捉所有的异样,应该不必或者慎用   ...:     print('Unexpected error:', sys.exc_info()[0])   ...:     OS error.

各个except之间的执行程序:

  • except程序捕捉try中抛出的异样
  • 越具体的异样应该越靠前,越个别的异样应该越靠后

可选的else语句

语法

try:    <语句>except <name>:    <语句>          #如果在try局部引发了名为'name'的异样,则执行这段代码else:    <语句>          #如果没有异样产生,则执行这段代码

如果try局部没有抛出异样,然而又必须执行的语句,则放在else语句中。

代码

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()

finally语句

finally语句用来定义在任何状况下都必须执行的语句。

In [1]: try:   ...:     raise KeyboardInterrupt   ...: finally:   ...:     print('Goodbye')   ...:     Goodbye---------------------------------------------------------------------------KeyboardInterrupt                         Traceback (most recent call last)<ipython-input-8-132d568ca0fb> in <module>()      1 try:----> 2     raise KeyboardInterrupt      3 finally:      4     print('Goodbye')      5 KeyboardInterrupt:

带return语句的finally执行程序

def p(x):    print(x)    return xdef t():    try:        return p(2)        print('haha')    finally:        return p(3)x = t()# 输入后果为:23# 返回值x为3

可见,在try块中,只有有finally语句,即便函数提前返回,也会在退出try块之前执行finally语句,因而返回值会被finally中的return语句代替。

综合应用示例

In [1]: def divide(x, y):   ...:     try:   ...:         result = x / y   ...:     except ZeroDivisionError:   ...:         print('division by zero!')   ...:     else:   ...:         print('result is ', result)   ...:     finally:   ...:         print('executing finally clause.')   ...:         In [2]: divide(2, 0)division by zero!executing finally clause.In [3]: divide(2, 1)result is  2.0executing finally clause.In [4]: divide('2', '1')executing finally clause.---------------------------------------------------------------------------TypeError                                 Traceback (most recent call last)<ipython-input-4-34bb38fa74fd> in <module>()----> 1 divide('2', '1')<ipython-input-1-4273ffa41b76> in divide(x, y)      1 def divide(x, y):      2     try:----> 3         result = x / y      4     except ZeroDivisionError:      5         print('division by zero!')TypeError: unsupported operand type(s) for /: 'str' and 'str'

论断:

  • 任何状况下finally语句都会执行。
  • 即便try局部中有return语句,也会在退出try块之前执行finally语句,并且返回值是finally中的return
  • 如果有异样没有被解决,则在执行实现finally语句之后会会抛出没有被解决的异样
  • 在理论应用中,finally通常用来开释额定的资源,比方文件或者网络连接

被动抛出异样

raise语句

In [1]: raise NameError('Hello')---------------------------------------------------------------------------NameError                                 Traceback (most recent call last)<ipython-input-1-64f372e60821> in <module>()----> 1 raise NameError('Hello')NameError: Hello

用户自定义异样

用户自定义异样类时,应该间接或者间接的继承自Exception类。

class CustomException(Exception):    def __init__(self, code, message):        self.code = code        self.message = messagetry:    raise CustomException(500, 'error')except CustomException as e:    print('{},{}'.format(e.code, e.message))# 输入后果:500,error

异样的传递

在函数内引发异样时,如果异样没有被捕捉到,那么它就会被流传到函数被调用的中央。

In [1]: def a():   ...:         raise Exception('Hello')   ...: In [2]: def b():   ...:         print('enter b')   ...:         a()  # 函数a中引发的异样,会传递到父函数的调用出   ...:         print('exit b')  # a中抛出异样之后传递到b,停止b的执行   ...:     In [3]: b()enter b---------------------------------------------------------------------------Exception                                 Traceback (most recent call last)<ipython-input-3-9c619ddbd09b> in <module>()----> 1 b()<ipython-input-2-f99a565bd6f8> in b()      1 def b():      2         print('enter b')----> 3         a()      4         print('exit b')      5 <ipython-input-1-6e68e60e93b5> in a()      1 def a():----> 2         raise Exception('Hello')Exception: Hello

记得帮我点赞哦!

精心整顿了计算机各个方向的从入门、进阶、实战的视频课程和电子书,依照目录正当分类,总能找到你须要的学习材料,还在等什么?快去关注下载吧!!!

朝思暮想,必有回响,小伙伴们帮我点个赞吧,非常感谢。

我是职场亮哥,YY高级软件工程师、四年工作教训,回绝咸鱼争当龙头的斜杠程序员。

听我说,提高多,程序人生一把梭

如果有幸能帮到你,请帮我点个【赞】,给个关注,如果能顺带评论给个激励,将不胜感激。

职场亮哥文章列表:更多文章

自己所有文章、答复都与版权保护平台有单干,著作权归职场亮哥所有,未经受权,转载必究!