Python 有两种常见的错误:语法错误和异常。

语法错误

语法错误也称之为解析错误。例如:

>>> while True print('Hello world') File "<stdin>", line 1, in ? while True print('Hello world') ^
SyntaxError: invalid syntax 

语法分析器指出了出错的一行,并且在最先找到的错误的位置标记了一个小小的’>箭头’。错误是由箭头前面的标记引起的。在这个例子中,检测到错误发生在函数print(),因为在它之前缺少一个冒号(‘:’)。文件名和行号会一并输出。

异常

即使一条语句或表达式在语法上是正确的,在运行它的时候,也有可能发生错误。在执行期间检测到的错误被称为异常(程序并没有崩溃) 大多数异常都不会被程序处理,导致产生类似下面的错误信息:

>>> 10 * (1/0)
Traceback (most recent call last): File "<stdin>", line 1, in ?
ZeroDivisionError: division by zero
>>> 4 + spam*3
Traceback (most recent call last): File "<stdin>", line 1, in ?
NameError: name 'spam' is not defined
>>> '2' + 2
Traceback (most recent call last): File "<stdin>", line 1, in ?
TypeError: Can't convert 'int' object to str implicitly 

最后的一行错误信息指示异常的原因。异常有不同的类型,其类型会作为消息的一部分打印出来:在这个例子中的类型有 ZeroDivisionError、NameError 和TypeError,打印出来的异常类型的字符串就是内置的异常的名称。用户也可以自定义异常,标准异常的名称都是内置的标识符(不是保留的关键字)。
异常文本最后一部分给出了异常的详细信息和引起异常的原因。
错误信息的前面部分以堆栈回溯的形式显示了异常发生的上下文。通常调用堆栈里会包含源代码的行信息,但是来自标准输入的源码不会显示行信息。
内置的异常列出了内置的异常以及它们的含义。

抛出异常

可以通过编程来选择处理部分异常。下面的例子会一直要求用户输入直到输入一个合法的整数为止,但允许用户中断这个程序(使用 Control-C 或系统支持的任何方法);注意用户产生的中断引发的是KeyboardInterrupt 异常。

>>> while True:
...     try:
...         x = int(input("Please enter a number: "))
...         break
...     except ValueError:
...         print("Oops!  That was no valid number.  Try again...")
... 

Try 语句按以下方式工作:
首先,执行try 子句(try 和关键字之间的语句)
如果未发生任何异常,忽略except 子句且try 语句执行完毕。
如果在try 子句执行过程中发生异常,跳过该子句的其余部分,如果异常的类型与except 关键字后面的异常名匹配,则执行except 子句,然后继续执行try语句之后的代码
如果异常的类型与except 关键字后面的异常名不匹配,它将被传递给上层的try语句;如果没有找到处理异常的代码,它就会成为一个未处理异常,程序会终止运行并显示一条错误信息。
Try 语句可能有多个子句,以指定不同的异常处理程序。不过至多只有一个处理程序将被执行。处理程序只处理发生在相应try 子句中的异常,不会处理同一个try 子句的其他处理程序中发生的异常。一个except 子句可以用带括号的元组列出多个异常的名字。例如:

... except (RuntimeError, TypeError, NameError):
...     pass 

最后一个except 子句可以省略异常名称(相当于else 一样,异常类型都不是上面的类型,最后一个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 语句没有抛出异常时执行一些代码。

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

当异常发生时,它可能带有相关数据,也称为异常的参数。参数的有无和类型取决于异常的类型。
except 子句可以在异常的名称之后指定一个变量,这个变量将绑定于一个异常实例,同时异常的参数将存放在实例的args 中。为方便起见,异常实例中定义了一个str()方法,因此异常的参数可以直接打印而不必引用.args。也可以在引发异常之前实例化一个异常,然后向它添加任何想要的属性:

>>> try:
...    raise Exception('spam', 'eggs')
... except Exception as inst:
...    print(type(inst))    # the exception instance
...    print(inst.args)     # arguments stored in .args
...    print(inst)          # __str__ allows args to be printed directly,
...                         # but may be overridden in exception subclasses
...    x, y = inst.args     # unpack args
...    print('x =', x)
...    print('y =', y)
...
<class 'Exception'>
('spam', 'eggs')
x = spam
y = eggs 

这里的 raise 表示引发一个指定的异常。
对于未处理的异常,如果它含有参数,那么参数会作为异常信息的最后一部分打印出来。
异常处理程序不仅处理直接发生在try 子句中的异常,而且还处理try 子句调用的函数(甚至间接调用的函数)引发的异常。例如:

>>> def this_fails():
...     x = 1/0
...
>>> try:
...     this_fails()
... except ZeroDivisionError as err:
...     print('Handling run-time error:', err)
...
Handling run-time error: int division or modulo by zero

引发异常

raise 语句允许程序员强行引发一个指定的异常。例如:

>>> raise NameError('HiThere')
Traceback (most recent call last): File "<stdin>", line 1, in ?
NameError: HiThere 

raise 的唯一参数指示要引发的异常。它必须是一个异常实例或异常类(从Exception 派生的类)。
如果需要引发一个异常,但不打算处理它,一个简单的raise 语句就可以重新引发异常:

>>> try:
...     raise NameError('HiThere')
... except NameError:
...     print('An exception flew by!')
...     raise
...
An exception flew by!
Traceback (most recent call last):
File "<stdin>", line 2, in ?
NameError: HiThere

用户定义的异常

程序可以通过创建新的异常类来命名自己的异常。异常通常应该继承Exception类,直接继承或者间接继承都可以。例如:

>>> 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!' 

在示例中,Exception 默认的init() 方法被自定义的MyError 重写了,新的__init() 方法简单地创建了value属性,这将替换默认的创建args属性的行为。
异常类可以像其他类一样做任何事情,但是通常都会比较简单,只提供一些属性以允许异常处理程序获取错误相关的信息。创建一个能够引发几种不同错误的模块时,一个通常的做法是为该模块定义的异常创建一个基类,然后基于这个基类为不同的错误情况创建特定的子类:

class Error(Exception): """Base class for exceptions in this module.""" pass class InputError(Error): """Exception raised for errors in the input. Attributes: expression -- input expression in which the error occurred message -- explanation of the error """ def __init__(self, expression, message): self.expression = expression self.message = message
class TransitionError(Error): """Raised when an operation attempts a state transition that's not allowed. Attributes: previous -- state at beginning of transition next -- attempted new state message -- explanation of why the specific transition is not allowed """ def __init__(self, previous, next, message): self.previous = previous self.next = next self.message = message 

大多数异常的名字都以”Error” 结尾,类似于标准异常的命名。
很多标准模块中都定义了自己的异常来报告在它们所定义的函数中可能发生的错误。类 这
一章给出了类的详细信息。

定义finally操作

Try 语句有另外一个可选的finally 子句,目的在于不管有没有发生异常,在离开try 语句之前总是执行finally 子句。当try 子句中发生了一个异常,并且没有except 语句处理(或者异常发生在except 或else 子句中),在执行完finally 子句之后将重新引发这个异常。try 语句由于break、contine或return 语句离开时,同样会执行finally 子句。
例如:

>>> def divide(x,y):
...     try:
...         result = x/y
...     except ZeroDivisionError:
...         print("division by zero!")
...     else:
...         print("relsut is",result)
...     finally:
...         print("executing finally clause")
...
>>> divide(2,1)
relsut is 2.0
executing finally clause
>>> divide(2,0)
division by zero!
executing finally clause
>>> divide("2","1")
executing finally clause
Traceback (most recent call last):File "<stdin>", line 1, in <module>File "<stdin>", line 3, in divide
TypeError: unsupported operand type(s) for /: 'str' and 'str'
>>>

正如您所看到的,在任何情况下都会执行finally 子句,由两个字符串相除引发的TypeError 异常没有被except 子句处理,因此在执行finally 子句后被重新引发。
在真实的应用程序中,finally 子句用于释放外部资源(例如文件或网络连接),无论这个资源的使用是否成功。

自动释放资源的相关预定义

有些对象定义了在不需要该对象时释放这个资源的相关操作,无论这个对象的使用是成功还是失败。下面的示例,它尝试打开一个文件并打印其内容到屏幕。

for line in open("myfile.txt"): print(line, end="")

这段代码的问题就是这部分代码执行完之后它还会让文件在一段不确定的时间内保持打开状态。这在简单的脚本中没什么,但是在大型应用程序中可能是一个问题。With语句可以确保像文件这样的对象资源总能及时准确地被释放掉。

with open("myfile.txt") as f: for line in f: print(line, end="") 

这和C#中的using 语法是类似的。
执行该语句后,文件f 将始终被关闭,即使在处理某一行时遇到了问题。

Python学习笔记之九——错误与异常相关推荐

  1. python学习笔记(九)之语句1

    python学习笔记(九)之语句1 print python2中,print是一个语句,python3中它是一个函数. 实例1: >> print "hello,world!&q ...

  2. Python学习笔记(九):类和对象

    Python学习笔记(九):类和对象 关于类和对象 Python学习笔记(九):类和对象 一.类和对象 类的定义 类的实例化 类对象的使用 二.self用法 三.类方法 实例方法 类方法 静态方法 静 ...

  3. python学习笔记(九)——文件和异常(重点)

    学文件的目的:数据不能可能一直在内存中存储,持久化存储到磁盘就需要用到文件了! 一.文件和上下文管理器(重点) 1.打开文件-open() 方法 Python open() 方法用于打开一个文件,并返 ...

  4. Python学习笔记__8章错误、调试和测试__8.1章错误处理

    # 这是学习廖雪峰老师python教程的学习笔记 1.概览 我们在运行程序或编写函数时,发生错误后,系统都会返回错误信息.我们可以通过某些机制,让错误信息更加明了 1.1.try try机制的格式就是 ...

  5. python学习笔记(九)异常处理

    python标准异常 异常名称 描述 BaseException 所有异常的基类 SystemExit 解释器请求退出 KeyboardInterrupt 用户中断执行(通常是输入^C) Except ...

  6. 深度之眼 - Python学习笔记——第八章 文件、异常和模块

    第八章 文件.异常和模块 实际应用中,我们绝大多数的数据都是通过文件的交互完成的 8.1 文件的读写 8.1.1 文件的打开 文件的打开通用格式 with open("文件路径", ...

  7. Python学习笔记(九)- 介绍Python语句(Introducing Python Statements)

    1.哪三样东西在类C语言中被需要但是在Python被忽略? 答:类C语言需要在某些语句中在测试周围加上括号,在每个语句的末尾使用分号,并在嵌套的代码块周围用大括号表示.如下面的类C语言: if (x ...

  8. python 学习笔记十九 django深入学习四 cookie,session

    缓存 一个动态网站的基本权衡点就是,它是动态的. 每次用户请求一个页面,Web服务器将进行所有涵盖数据库查询到模版渲染到业务逻辑的请求,用来创建浏览者需要的页面.当程序访问量大时,耗时必然会更加明显, ...

  9. Python数据挖掘学习笔记】九.回归模型LinearRegression简单分析氧化物数据

    #2018-03-23 16:26:20 March Friday the 12 week, the 082 day SZ SSMR [Python数据挖掘学习笔记]九.回归模型LinearRegre ...

最新文章

  1. 你们需要客户端吗?大话软件企业的营销(上)
  2. CentOS7编译安装nginx-1.8.1和编译参数
  3. HTML怎么限制每行字数,JS实现每行固定字数,自动换行
  4. thinkphp 内置函数详解
  5. plupload 中文php,简单集成wangEditor plupload 到Tp3.2
  6. 酷开网络首推“无界空间”,酷开系统8正式发布!
  7. 在SUM()行数中使用SQL变量导致不可预测结果
  8. scala函数进阶篇
  9. Windows 7 卸载 IE10
  10. stm32h750电路_STM32H750开发板
  11. matlab矩阵特征值分解,矩阵特征值分解与奇异值分解含义解析及应用
  12. ImagePicker 打开前置摄像头
  13. TSC打印机使用教程终极版(转)
  14. aix服务器删除文件命令,AIX删除文件系统
  15. 关于2-3-4树和红黑树的简单理解
  16. 一个冷门json类JacksonJsonParser中的坑
  17. ONVIF工具使用说明
  18. Linux 命令一览表,持续更新中
  19. 网易mc显示服务器异常,明日之后:一天之内3次服务器异常,网易果真是“土豆服务器”!...
  20. 数独游戏思路html,数独游戏的前端实现

热门文章

  1. MSE考研百日冲刺-98
  2. 略举Excel实用技巧
  3. /dev/mapper/vg_xxx-lv_root 100% 磁盘打满解决方式及思路
  4. element自定义表单验证上传身份证正反面的实现
  5. 如何在H5中完美融入VR技术?道可云VR全景教程!
  6. Linux6安装bind错误,CentOS 7.6环境下Bind 9的安装与配置
  7. IOS中Segue的使用
  8. 推荐开源 APS 高级排程系统
  9. matlab牛顿拉夫逊算法,牛顿拉夫逊法程序设计
  10. VS2022配置OpenGL+GLAD