《Python入门指南》第五部分-异常 - 指南
这是Python教程。在本教程中,您将学习Python语言的基础知识和更高级的主题。
目录
- Python语言
- 交互式Python
- 关键词
- 文件
- 面向对象编程
- 异常
- 迭代
Python 中的异常
在 Python 教程的这一部分,我们讨论了 Python 中的异常。
执行过程中检测到的错误称为异常。在执行期间 我们的申请可能会出错。光盘可能会满,我们却不能保存我们的档案。网络连接可能会断线,我们的应用程序可能会尝试 连接到一个网站。所有这些都可能导致我们的应用崩溃。为防止这种情况的出现,我们必须应对所有可能发生的错误使用异常处理。
在 Python 中捕捉异常
在 Python 中,我们有以下语法来处理异常情况:
try:
# do something
except ValueError:
# handle ValueError exception
except (IndexError, ZeroDivisionError):
# handle multiple exceptions
# IndexError and ZeroDivisionError
except:
# handle all other exceptions
finally:
# cleanup resources
我们期望发生异常的代码写在块中。关键字捕获程序中指定或剩余的异常。可选块始终被执行;它用于清理打开的文件或数据库连接等资源。tryexceptfinally
零除错误
零不能作为除数。如果我们尝试这样做,脚本会被中断。ZeroDivisionError
#!/usr/bin/env python
# zero_division.py
def input_numbers():
a = float(input("Enter first number:"))
b = float(input("Enter second number:"))
return a, b
x, y = input_numbers()
print(f"{x} / {y} is {x/y}")
在这个脚本中,我们从控制台得到两个数字。我们把这两个数字分开。如果第二个数字为零,则会出现异常。
Enter first number:3
Enter second number:0
Traceback (most recent call last):
File "C:/Users/Jano/PycharmProjects/Simple/simple.py", line 14, in
print(f"{x} / {y} is {x/y}")
ZeroDivisionError: float division by zero
我们可以用两种方式处理这件事。
#!/usr/bin/env python
# zero_division2.py
def input_numbers():
a = float(input("Enter first number:"))
b = float(input("Enter second number:"))
return a, b
x, y = input_numbers()
while True:
if y != 0:
print(f"{x} / {y} is {x/y}")
break
else:
print("Cannot divide by zero")
x, y = input_numbers()
首先,我们只需检查该值是否不为零。如果该值为零,我们将打印一条警告消息,并再次重复输入循环。通过这种方式,我们处理了错误,脚本没有中断。
$ ./zero_division2.py
Enter first number:4
Enter second number:0
Cannot divide by zero
Enter first number:5
Enter second number:0
Cannot divide by zero
Enter first number:5
Enter second number:6
5.0 / 6.0 is 0.8333333333333334
另一种方法是使用例外。
#!/usr/bin/env python
# zerodivision3.py
def input_numbers():
a = float(input("Enter first number:"))
b = float(input("Enter second number:"))
return a, b
x, y = input_numbers()
try:
print(f"{x} / {y} is {x/y}")
except ZeroDivisionError:
print("Cannot divide by zero")
x, y = input_numbers()
我们将代码放在关键字后预期出现异常的地方。如果引发异常,关键字会捕获异常。异常类型在关键字后指定。。tryexceptexcept
except ValueError:
pass
except (IOError, OSError):
pass
为了处理更多例外,我们可以选择使用除关键词外的更多例外,或者放置 例外名称包含在元组内。
ValueError
ValueError当内置作或函数接收 时 会被提升 一个类型正确但值不合适的参数,以及情境 没有更精确的例外描述。
#!/usr/bin/env python
# value_error.py
def read_age():
age = int(input("Enter your age: "))
if age < 0 or age > 130:
raise ValueError("Invalid age")
return age
try:
val = read_age()
print(f"Your age is {val}")
except ValueError as e:
print(e)
在示例中,我们有一个函数将年龄读入。当用户提供错误的数值时,我们会抛出例外。ValueError
if age < 0 or age > 130:
raise ValueError("Invalid age")
return age
负年龄说法毫无意义,也没有记录到一个人 现代已有130年以上历史。
Python多个异常
可以在一个子句中捕获多个异常。except
#!/usr/bin/env python
# multiple_exceptions.py
import os
try:
os.mkdir('newdir')
print('directory created')
raise RuntimeError("Runtime error occurred")
except (FileExistsError, RuntimeError) as e:
print(e)
代码示例在一条语句中捕获两个异常:和.exceptFileExistsErrorRuntimeError
os.mkdir('newdir')
使用该方法创建了一个新目录。如果目录已存在,则会触发。os.mkdirFileExistsError
raise RuntimeError("Runtime error occurred")
我们使用关键字手动引发运行时异常。raise
Python异常参数
异常可以有一个相关值,指示错误的详细原因。该值放在关键字后面。as
#!/usr/bin/env python
# exception_argument.py
try:
a = (1, 2, 3, 4)
print(a[5])
except IndexError as e:
print(e)
print("Class:", e.__class__)
通过异常对象,我们可以获取错误消息或类名。
$ ./exception_as.py
tuple index out of range
Class:
Python异常层次结构
异常按层次结构组织,是所有异常的父级。Exception
#!/usr/bin/env python
# interrupt.py
try:
while True:
pass
except KeyboardInterrupt:
print("Program interrupted")
脚本开始,循环往复。如果我们按+, 我们打断了这个循环。在这里,我们抓住了异常。CtrlCKeyboardInterrupt
Exception
BaseException
KeyboardInterrupt
#!/usr/bin/env python
# interrupt2.py
try:
while True:
pass
except BaseException:
print("Program interrupted")
这个例子也适用。还捕捉到键盘中断;除其他例外情况外。然而,这不是一种好的做法。我们应该在条款中抓住具体的例外情况。BaseExceptionexcept
Python 用户自定义例外
如果我们愿意,我们可以创建自己的例外。我们通过定义一个新的异常类来实现。
#!/usr/bin/env python
# user_defined.py
class BFoundEx(Exception):
def __init__(self, value):
self.par = value
def __str__(self):
return f"BFoundEx: b character found at position {self.par}"
string = "There are beautiful trees in the forest."
pos = 0
for i in string:
try:
if i == 'b':
raise BFoundEx(pos)
pos = pos + 1
except BFoundEx as e:
print(e)
在我们的代码示例中,我们创建了一个新的异常。异常源于基类。如果我们在字符串中发现字母b的任何出现,我们将异常。Exceptionraise
$ ./user_defined.py
'BFoundEx: b character found at position 10'
清理工作
有一个关键字,它总是被执行。无论是否引发异常。它通常用于对程序中的资源进行一些清理。finally
#!/usr/bin/env python
# cleanup.py
f = None
try:
f = open('data.txt', 'r')
contents = f.readlines()
for line in contents:
print(line.rstrip())
except IOError:
print('Error opening file')
finally:
if f:
f.close()
在我们的例子中,我们尝试打开一个文件。如果无法打开文件,则会被提出 a。如果我们打开文件,我们 想关闭文件处理程序。为此,我们使用关键词。 在最后一个区块中,我们检查文件是否被打开。如果它被打开, 我们关上它。这是我们处理数据库时常见的编程构思。 在那里,我们也会清理打开的数据库连接。IOErrorfinally
堆栈跟踪
堆栈跟踪显示了抛出未捕获异常时的调用堆栈(到那时为止被调用的函数堆栈)。Python模块提供了一个标准接口,用于提取、格式化和打印Python程序的堆栈跟踪。它精确地模仿了Python解释器在打印堆栈跟踪时的行为。traceback
#!/usr/bin/env python
# stacktrace_ex.py
import traceback
def myfun():
def myfun2():
try:
3 / 0
except ZeroDivisionError as e:
print(e)
print("Class:", e.__class__)
for line in traceback.format_stack():
print(line.strip())
myfun2()
def test():
myfun()
test()
在示例中,嵌套函数中有一个除以零的例外。myfun2
for line in traceback.format_stack():
它从当前内存中提取原始的堆栈框架并将其格式化为一组数组。我们遍历数组列表 带有for循环。format_stack
$ ./stacktrace_ex.py
division by zero
Class:
File "C:/Users/Jano/PycharmProjects/Simple/simple.py", line 30, in
test()
File "C:/Users/Jano/PycharmProjects/Simple/simple.py", line 27, in test
myfun()
File "C:/Users/Jano/PycharmProjects/Simple/simple.py", line 23, in myfun
myfun2()
File "C:/Users/Jano/PycharmProjects/Simple/simple.py", line 20, in myfun2
for line in traceback.format_stack():
在程序中,我们可以看到调用栈——即被调用函数的顺序 导致了错误。
本章我们介绍了Python中的例外情况。

浙公网安备 33010602011771号