暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Python 基础知识整理 - 错误和异常(1)

数据库杂货铺 2021-12-19
6070

错误和异常

 

到目前为止,错误消息还没有被提及,但是如果已经尝试了这些示例,你可能已经看到了一些。至少有两种明显不同的错误:语法错误和异常。

 

语法错误

 

语法错误,也称为解析错误,可能是你在学习 Python 时遇到的最常见的抱怨:

 

while True print('Hello world')

 

运行结果:

 

C:\Python310>python 2.py
File "C:\Python310\2.py", line 1
while True print('Hello world')
^^^^^^^^^^^^^^^^^^^^^^^^^
SyntaxError: invalid syntax. Perhaps you forgot a comma?

 

解析器重写出现问题的行,并显示一个小箭头,指向行中检测到错误的最早点。该错误是由箭头前面的标记引起的(或至少在该标记处检测到):在本例中,该错误是在函数 print() 处检测到的,因为它前面缺少冒号(':')。错误信息会输出文件名和行号,以便在输入来自脚本的情况下知道在哪里查找。

 

异常

 

即使一个语句或表达式在语法上是正确的,当试图执行它时也可能会引发错误。在执行过程中检测到的错误称为异常,并且是在一定条件下产生的:你将很快学会如何在 Python 程序中处理它们。但是,大多数异常在程序中都不会被处理,这会导致错误消息,如下所示:

 

10 * (1/0)

 

运行结果:

 

C:\Python310>python 2.py
Traceback (most recent call last):
File "C:\Python310\2.py", line 1, in <module>
10 * (1/0)
ZeroDivisionError: division by zero

4 + spam*3

  

运行结果:

 

C:\Python310>python 2.py
Traceback (most recent call last):
File "C:\Python310\2.py", line 1, in <module>
4 + spam*3
NameError: name 'spam' is not defined

'2' + 2

  

运行结果:

 

C:\Python310>python 2.py
Traceback (most recent call last):
File "C:\Python310\2.py", line 1, in <module>
'2' + 2
TypeError: can only concatenate str (not "int") to str

 

错误消息的最后一行说明发生了什么。异常有不同的类型,类型会作为消息的一部分输出:示例中的类型有 ZeroDivisionErrorNameError TypeError。作为异常类型输出的字符串是发生的内置异常的名称。这一点适用于所有内置异常,但不一定适用于用户定义的异常(尽管这是一个有用的约定)。标准异常名称是内置标识符(不是保留关键字)。

 

该行的其余部分根据异常的类型和原因提供详细信息。

 

错误消息的前面部分以堆栈回溯的形式显示异常发生的上下文。通常,它包含一个堆栈回溯,列出源代码行;但是,它不会显示从标准输入读取的行。

 

处理异常

 

可以编写程序处理特定异常。看看下面的例子,它要求用户输入一个有效的整数,但允许用户中断程序(使用Control-C或操作系统支持的其他方式);请注意,用户生成的中断通过引发 KeyboardInterrupt 异常发出信号。

 

while True:
try:
x = int(input("请输入数字: "))
break
except ValueError:
print("不是有效数字,请再次尝试...")

 

try 语句的工作原理如下。

 

 首先,执行 try 子句(try except 关键字之间的语句)。

 

 如果未发生异常,则跳过 except 子句并完成 try 语句的执行。

 

 如果在执行 try 子句期间发生异常,则跳过该子句的其余部分。然后,如果其类型与 except 关键字命名的异常匹配,则执行 except 子句,然后继续执行 try 之后的语句。

 

 如果发生与 except 子句中指定的异常不匹配的异常,则将其传递给外部 try 语句;如果未找到处理程序,则它是一个未处理的异常,执行将停止,并显示一条消息,如上所示。

 

try 语句可以有多个 except 子句,用于为不同的异常指定处理程序。最多将执行一个处理程序。处理程序只处理相应 try 子句中出现的异常,而不处理其他 try 语句的处理程序中出现的异常。except 子句可以将多个异常指定在带括号的元组中,例如:

 

except (RuntimeError, TypeError, NameError):
pass

 

如果 except 子句中的类是同一个类或其基类,则该类与异常兼容(但相反,列出派生类的 except 子句与基类不兼容)。例如,以下代码将按该顺序打印 BCD

 

class B(Exception):
pass


class C(B):
pass


class D(C):
pass


for cls in [B, C, D]:
try:
raise cls()
except D:
print("D")
except C:
print("C")
except B:
print("B")

 

请注意,如果 except 子句被颠倒(首先是 except B),它将打印 BBB,即触发第一个匹配的 except 子句。

 

最后一个 except 子句可以省略异常名称,用作通配符。使用时要格外小心,因为这样很容易掩盖真正的编程错误!它还可用于打印错误消息,然后重新引发异常(也允许调用方处理异常):

 

import sys


try:
f = open('1.txt')
s = f.readline()
i = int(s.strip())
except OSError as err:
print("OS 错误: {0}".format(err))
except ValueError:
print("无法将数据转换为整数。")
except:
print("意外错误:", sys.exc_info()[0])
raise

 

try … except 语句有一个可选的 else 子句,当该子句出现时,必须在所有 except 子句之后。如果 try 子句没有引发异常,必须执行某些代码,这种情况下就非常有用。例如:

 

创建一个 2.txt 文件:

 

{"1": "吕布", "2" :"赵云"}

import sys
for arg in sys.argv[1:]:
try:
f = open(arg, 'r')
except OSError:
print('不能打开', arg)
else:
print(arg, '有', len(f.readlines()), '行')
f.close()

  

调用程序:

 

C:\Python310>python 2.py 2.txt

 

运行结果:

 

2.txt 有 1 行

 

使用 else 子句比向 try 子句添加其他代码要好,因为它可以避免意外捕获不是由 try … except 语句保护的代码引发的异常。

 

当异常发生时,它可能有一个关联的值,也称为异常参数。参数的展现和类型取决于异常类型。

 

except 子句可以在异常名称后指定变量。变量绑定到异常实例,其参数存储在 instance.args。为方便起见,异常实例定义了 __str__() 以便可以直接打印参数,而无需引用 .args。也可以在引发异常之前先实例化异常,并根据需要向其添加任何属性。

 

try:
raise Exception('书名', '作者')
except Exception as inst:
print(type(inst)) # 异常实例
print(inst.args) # 参数存储在 .args
print(inst) # __str__ 允许 args 被直接输出,
# 可也可能在异常的子类中被重写
x, y = inst.args # 解包 args
print('x =', x)
print('y =', y)

 

运行结果:

 

<class 'Exception'>
('书名', '作者')
('书名', '作者')
x = 书名
y = 作者

 

如果异常有参数,它们将作为未处理异常消息的最后一部分(详细信息)打印。

 

异常处理程序不仅处理在 try 子句中立即发生的异常,还处理在 try 子句中调用(甚至间接调用)的函数中发生的异常。例如:

 

def fails():
x = 1/0


try:
fails()
except ZeroDivisionError as err:
print('处理运行时错误:', err)

 

运行结果:

 

处理运行时错误: division by zero

 

 

 

官方文档:

https://docs.python.org/3.9/tutorial/errors.html


文章转载自数据库杂货铺,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论