• 日常搜索
  • 百度一下
  • Google
  • 在线工具
  • 搜转载

如何在 Python 中处理异常

在程序执行过程中遇到错误是很常见的。您可能必须处理的两种常见错误是语法错误和异常。错误键入代码时会发生语法错误。在这种情况下,错误行被解析器重复,箭头指向检测到错误的最早位置。

如何在 Python 中处理异常  第1张

异常不同于语法错误。它们发生在程序执行期间发生意外情况时。例如,假设您要求用户输入一个数字以执行除法。现在,如果用户输入一个字符串而不是一个数字,并且您尝试将一个数字除以给定的输入,程序将输出一个TypeError.

当您没有正确处理异常时,程序将突然退出,因为它不知道在这种情况下该做什么。下面的代码就是这样一个例子:

keep_asking = True
 
while keep_asking:
    x = int(input("Enter a number: "))
    print("Dividing 50 by", x,"will give you :", 50/x)

只要您输入一个整数输入值,程序就会正常工作。但是,一旦您输入一个字符串甚至一个十进制数字作为输入,您就会得到一个ValueError异常。

python exceptions.py 
Enter a number: n
Traceback (most recent call last):
  File "/home/vaati/Desktop/exceptions.py", line 4, in <module>
    x = int(input("Enter a number: "))
ValueError: invalid literal for int() with base 10: 'n'

从上面的回溯中,我们可以看到用户输入了一个字符串 n 而不是一个导致ValueError. 回溯还向我们展示了错误的确切位置,即第 4 行允许我们返回代码并修复它。

在本教程中,您将学习如何在 Python 中正确处理和引发异常。

  • 一些常见的例外

  • 处理异常

  • 使用 Else 子句

  • 使用 finally 子句进行清理

  • 一个更复杂的例子

  • 用户定义的异常

一些常见的例外

以下是您在编写程序时可能会遇到的一些基本例外情况。您可以在官方网站上阅读更多内置异常。

  • NameError:当程序找不到本地或全局名称时会引发此异常。无法找到的名称包含在错误消息中。

  • TypeError:当一个函数被传递一个不适当类型的对象作为其参数时,会引发此异常。错误消息中提供了有关错误类型的更多详细信息。

  • ValueError:当函数参数的类型正确但值不合适时,会发生此异常。

  • NotImplementedError:当一个对象应该支持一个操作但它还没有实现时,就会引发这个异常。当给定函数不支持输入参数的类型时,不应使用此错误。在这些情况下,引发TypeError异常更为合适。

  • ZeroDivisionError:当您将除法或模运算的第二个参数设置为零时,将引发此异常。

  • FileNotFoundError:当程序请求的文件或目录不存在时引发此异常。

就像上面的名称一样,大多数例外都有不言自明的名称。

处理异常

文章开头的代码要求用户输入一个整数作为输入。如果用户没有提供整数输入,程序将停止执行并引发值错误异常。在本节中,我们将编写一些代码来告诉用户他们的输入不是有效的整数值。

处理异常使我们的程序即使在发生错误时也能继续执行。

尝试除外条款

该过程的第一步是在try子句中包含您认为可能引发异常的代码。下一步是使用except关键字来处理上面代码中发生的异常。修改后的用户输入代码如下所示:

keep_asking = True
 
while keep_asking:
    try:
        x = int(input("Please enter a number: "))
        print("Dividing 50 by", x,"will give you :", 50/x)
    except ValueError:
        print("The input was not an integer. Please try again...")

这里发生的是程序尝试执行try子句内的代码。如果没有引发异常,程序将跳过该except子句,其余代码正常执行。如果引发异常,程序将跳过try子句中的剩余代码,异常类型与关键字后面的异常名称匹配except。如果匹配,except则先执行子句内的代码,然后再try正常执行子句后的其余代码。

当您输入一个整数作为输入时,程序会为您提供除法的最终结果。当提供非整数值时,程序会打印一条消息,要求您尝试再次输入整数。请注意,这一次,当您提供一些无效输入时,程序不会突然退出。

如果您输入一个不是整数的数字,您将在终端上获得以下输出。

Please enter a number: n
The input was not an integer. Please try again...
Please enter a number:

您可以有多个except子句来处理不同的异常。请记住,这些处理程序只会处理相应try子句中发生的异常。它们不会处理在其他异常处理程序中引发的任何异常。

您还可以使用单个except子句处理多个异常,方法是将这些异常作为tuple.

except (ZeroDivisionError, ValueError, TypeError):
    print("Something has gone wrong..")
    # code to deal with the exception

最后,您还可以在except关键字后面省略异常的名称。通常不建议这样做,因为代码现在将捕获所有异常并以相同的方式处理它们。这不是最优的,因为您将以与处理TypeError异常相同的方式处理ZeroDivisionError异常。在处理异常时,最好尽可能具体,只捕获你能处理的。

捕获所有异常的一种可能用途是在屏幕上正确打印出异常错误,如下面的代码:

import math
import sys
 
try:
    result = math.factorial(2.4)
except:
    print("Something Unexpected has happened.",sys.exc_info()[0])
else:
    print("The factorial is", result)

使用 Else 子句

您还可以else在语句中使用子句try ... except。如果该子句没有引发任何异常,则该else子句旨在包含需要执行的代码。try这对于确保您不会将任何代码添加到try您不打算捕获其异常的块中很有用。值得一提的是,如果您决定使用else子句,则应将其包含在所有except子句之后但在finally块之前。

在我们的例子中,我们可以在else块内移动打印除法结果的行。

keep_asking = True
 
while keep_asking:
    try:
        x = int(input("Please enter a number: "))
    except ValueError:
        print("The input was not a valid integer. Please try again...")
    else:
        print("Dividing 50 by", x,"will give you :", 50/x)

使用 finally 子句进行清理

假设您在try块内编写了一些代码,该代码应该通过利用大量资源来执行任务。使用完这些资源后,释放这些资源很重要。这可以通过使用finally子句轻松实现。

finally无论try块是否引发异常,子句内的代码都会始终执行。您可以通过运行以下代码来验证这一点:

keep_asking = True
 
while keep_asking:
    try:
        x = int(input("Please enter a number: "))
    except ValueError:
        print("The input was not a valid integer. Please try again...")
    else:
        print("Dividing 50 by", x,"will give you :", 50/x)
    finally:
        print("Already did everything necessary.")

如果except您指定的任何子句不处理引发的异常,则在finally块内执行代码后再次引发相同的异常。

一个更复杂的例子

在本节中,我们将编写一个程序来处理多个异常。就像前面的例子一样,我们将执行一些数学运算。但是,这次我们将从列表中获取输入。

以下代码检查两个异常,TypeError并且ValueError. 该else块用于打印阶乘。您可以在输出中看到,只有在没有引发异常时才会执行此代码。

import math
 
number_list = [10,-5,1.2,'apple']
 
for number in number_list:
    try:
        number_factorial = math.factorial(number)
    except TypeError:
        print("Factorial is not supported for given input type.")
    except ValueError:
        print("Factorial only accepts positive integer values.", number," is not a positive integer.")
    else:
        print("The factorial of",number,"is", number_factorial)
    finally:
        print("Release any resources in use.")

上面的代码产生以下输出:

The factorial of 10 is 3628800
Releasing any resources in use.
 
Factorial only accepts positive integer values. -5  is not a positive integer.
Releasing any resources in use.
 
Factorial only accepts positive integer values. 1.2  is not a positive integer.
Releasing any resources in use.
 
Factorial is not supported for given input type.
Releasing any resources in use.

另一件值得注意的事情是,finally子句中的代码是针对列表中的每个项目执行的。

用户定义的异常

有时,您想引发 Python 未提供的异常。用户定义的异常使程序更具可读性。例如,假设您正在设计一个程序的一部分来检查用户提交的优惠券代码是否有效,那么您需要为此目的创建一个自定义异常。

自定义异常继承自 python 基 Exception 类,如下所示。

class CouponError(Exception):    
pass

异常的定义也类似于 Python 异常,以 Error 结尾,尽管这是可选的。

一旦定义了异常,您就可以在您的程序中使用它,如下所示。

coupon_list = ['FREEAUG','STUDENT','FREEWEEK']
x = str(input("Enter coupon: "))
if x not in coupon_list:
    raise CouponError
print('coupon is Valid')

在上面的代码中,我们要求用户提供优惠券代码,如果他们提供的优惠券代码不在 中coupon_list,CouponError则引发 a。

Enter coupon: GT
Traceback (most recent call last):
  File "/home/vaati/Desktop/exceptions.py", line 10, in <module>
    raise CouponError
__main__.CouponError

要自定义错误,甚至更多,您可以为用户定义更友好的消息。

class CouponError(Exception):
   def __init__(self, coupon):
       self.coupon = coupon
 
 
   def __str__(self):
        return  (self.coupon) + ' is an invalid coupon'

现在,如果您再次运行该程序,用户会收到更友好的错误消息

Ente
r coupon: FREE
Traceback (most recent call last):
  File "/home/vaati/Desktop/exceptions.py", line 15, in <module>
    raise CouponError(coupon)
__main__.CouponError: FREE is an invalid coupon

最后的想法

我希望本教程能帮助你理解 Python 中的异常处理。此外,不要犹豫,看看我们在市场上有哪些可供出售和学习的产品,不要犹豫,使用下面的提要提出任何问题并提供您宝贵的反馈。


文章目录
  • 一些常见的例外
  • 处理异常
    • 尝试除外条款
  • 使用 Else 子句
  • 使用 finally 子句进行清理
  • 一个更复杂的例子
  • 用户定义的异常
  • 最后的想法
  • 发表评论