辨别 Exception 和 Syntax Error
在写 Python 程序的时候常常会报错,报错通常有以下两种状况:
- 语法错误(Syntax Error): 局部语法错误属于异样
- 异样(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/0
ZeroDivisionError: 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: asd
No valid number.
多个 except
In [4]: import sys
In [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 x
def t():
try:
return p(2)
print('haha')
finally:
return p(3)
x = t()
# 输入后果为:2
3
# 返回值 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.0
executing 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 = message
try:
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 高级软件工程师、四年工作教训,回绝咸鱼争当龙头的斜杠程序员。
听我说,提高多,程序人生一把梭
如果有幸能帮到你,请帮我点个【赞】,给个关注,如果能顺带评论给个激励,将不胜感激。
职场亮哥文章列表:更多文章
自己所有文章、答复都与版权保护平台有单干,著作权归职场亮哥所有,未经受权,转载必究!