# Python 使用`try`,`except`和`finally`语句的异常处理 > 原文: [https://www.programiz.com/python-programming/exception-handling](https://www.programiz.com/python-programming/exception-handling) #### 在本教程中,您将在示例的帮助下使用`try`,`except`和`finally`语句学习如何在 Python 程序中处理异常。 ## Python 异常 Python 有许多[内置异常](/python-programming/exceptions),这些异常在您的程序遇到错误(程序中的某些地方出错)时引发。 当发生这些异常时,Python 解释器将停止当前进程并将其传递给调用进程,直到对其进行处理。 如果不处理,程序将崩溃。 例如,让我们考虑一个程序,其中有一个[函数](/python-programming/function) `A`,该函数调用函数`B`,该函数又调用函数`C`。 如果异常在函数`C`中发生,但未在`C`中处理,则该异常传递给`B`,然后传递给`A`。 如果从未处理过,则会显示一条错误消息,并且我们的程序突然突然中止。 * * * ## 在 Python 中捕捉异常 在 Python 中,可以使用`try`语句处理异常。 可能引发异常的关键操作放在`try`子句中。 处理异常的代码写在`except`子句中。 因此,一旦捕获到异常,我们可以选择要执行的操作。 这是一个简单的例子。 ```py # import module sys to get the type of exception import sys randomList = ['a', 0, 2] for entry in randomList: try: print("The entry is", entry) r = 1/int(entry) break except: print("Oops!", sys.exc_info()[0], "occurred.") print("Next entry.") print() print("The reciprocal of", entry, "is", r) ``` **输出** ```py The entry is a Oops! occurred. Next entry. The entry is 0 Oops! occured. Next entry. The entry is 2 The reciprocal of 2 is 0.5 ``` 在此程序中,我们遍历`randomList`列表的值。 如前所述,可能导致异常的部分位于`try`块内。 如果没有异常,则跳过`except`块,继续正常流程(最后一个值)。 但是,如果发生任何异常,它将被`except`块(第一个和第二个值)捕获。 在这里,我们使用`sys`模块内的`exc_info()`函数打印异常的名称。 我们可以看到`a`导致`ValueError`和`0`导致`ZeroDivisionError`。 由于 Python 中的每个异常都继承自基本`Exception`类,因此我们还可以通过以下方式执行上述任务: ```py # import module sys to get the type of exception import sys randomList = ['a', 0, 2] for entry in randomList: try: print("The entry is", entry) r = 1/int(entry) break except Exception as e: print("Oops!", e.__class__, "occurred.") print("Next entry.") print() print("The reciprocal of", entry, "is", r) ``` 该程序具有与上述程序相同的输出。 * * * ## 捕获 Python 中的特定异常 在上面的示例中,我们没有在`except`子句中提及任何特定的异常。 这不是一个好的编程习惯,因为它将捕获所有异常并以相同的方式处理每种情况。 我们可以指定`except`子句应捕获的异常。 一个`try`子句可以具有任意数量的`except`子句来处理不同的异常,但是,如果发生异常,则仅执行一个子句。 我们可以使用值的元组在`except`子句中指定多个异常。 这是示例伪代码。 ```py try: # do something pass except ValueError: # handle ValueError exception pass except (TypeError, ZeroDivisionError): # handle multiple exceptions # TypeError and ZeroDivisionError pass except: # handle all other exceptions pass ``` * * * ## 在 Python 中引发异常 在 Python 编程中,在运行时发生错误时会引发异常。 我们还可以使用`raise`关键字手动引发异常。 我们可以选择将值传递给异常,以阐明引发该异常的原因。 ```py >>> raise KeyboardInterrupt Traceback (most recent call last): ... KeyboardInterrupt >>> raise MemoryError("This is an argument") Traceback (most recent call last): ... MemoryError: This is an argument >>> try: ... a = int(input("Enter a positive integer: ")) ... if a <= 0: ... raise ValueError("That is not a positive number!") ... except ValueError as ve: ... print(ve) ... Enter a positive integer: -2 That is not a positive number! ``` * * * ## Python `try-else`子句 在某些情况下,如果`try`中的代码块运行无误,则可能要运行某个代码块。 对于这些情况,可以在`try`语句中使用可选的`else`关键字。 **注意**:`else`子句不会处理`else`子句中的异常。 让我们看一个例子: ```py # program to print the reciprocal of even numbers try: num = int(input("Enter a number: ")) assert num % 2 == 0 except: print("Not an even number!") else: reciprocal = 1/num print(reciprocal) ``` **输出**: 如果我们传递一个奇数: ```py Enter a number: 1 Not an even number! ``` 如果我们传递一个偶数,则将计算并显示倒数。 ```py Enter a number: 4 0.25 ``` 但是,如果传递 0,则会得到`ZeroDivisionError`,因为`else`内部的代码块未由前面的`except`处理。 ```py Enter a number: 0 Traceback (most recent call last): File "", line 7, in reciprocal = 1/num ZeroDivisionError: division by zero ``` * * * ## Python `try-finally` Python 中的`try`语句可以具有可选的`finally`子句。 该子句无论如何执行,通常用于释放外部资源。 例如,我们可能通过网络或使用文件或图形用户界面(GUI)连接到远程数据中心。 在所有这些情况下,无论程序是否成功运行,我们都必须在程序停止之前清理资源。 这些操作(关闭文件,GUI 或与网络断开连接)在`finally`子句中执行,以确保执行。 这是[文件操作](/python-programming/file-operation)的示例来说明这一点。 ```py try: f = open("test.txt",encoding = 'utf-8') # perform file operations finally: f.close() ``` 这种类型的构造可确保即使在程序执行期间发生异常,也可以关闭文件。