《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

注意:以下示例演示了异常在Python中的工作方式。更直接的方法是确保除数不为零,而不是catch。
#!/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中的例外情况。

posted @ 2026-01-20 11:34  gccbuaa  阅读(0)  评论(0)    收藏  举报