Python异常处理
try...except
 
摘要:在本节中,你将学习如何使用 Python 的 try...except 语句来优雅地处理异常。
在 Python 中,主要有两种错误:语法错误和异常。
语法错误
当你编写了无效的 Python 代码时,将会出现语法错误。例如:
current = 1
if current < 10
current += 1
 
如果你尝试运行这段代码,将会出现以下错误:
File "d:/python/try-except.py", line 2if current < 10^
SyntaxError: invalid syntax
 
在这个例子中,由于 if 语句后面缺少冒号(:),Python 解释器检测到了该错误。
Python 解释器会显示发生错误的文件名和行号,以便你进行修正。
异常
即使你的代码语法有效,在执行过程中也可能导致错误。
在 Python 中,执行期间发生的错误称为异常。异常的成因主要来自代码执行的环境。例如:
- 读取一个不存在的文件。
 - 连接一个离线的远程服务器。
 - 用户输入错误。
 
当发生异常时,程序不会自动处理它。这会导致出现错误消息。
例如,以下程序用于计算销售增长率:
# get input net sales
print('Enter the net sales for')previous = float(input('- Prior period:'))
current = float(input('- Current period:'))# calculate the change in percentage
change = (current - previous) * 100 / previous# show the result
if change > 0:result = f'Sales increase {abs(change)}%'
else:result = f'Sales decrease {abs(change)}%'print(result)
 
其工作原理:
- 首先,提示用户输入两个数字:上一期和当期的净销售额。
 - 然后,计算销售增长率(百分比)并显示结果。
 
当你运行该程序并输入120'作为当期净销售额时,Python 解释器将输出以下内容:
Enter the net sales for
- Prior period:100
- Current period:120'
Traceback (most recent call last):File "d:/python/try-except.py", line 5, in <module>current = float(input('- Current period:'))
ValueError: could not convert string to float: "120'"
 
Python 解释器显示了一个包含异常详细信息的回溯信息:
- 导致异常的源代码文件路径(d:/python/try-except.py)。
 - 导致异常的确切代码行(第 5 行)。
 - 导致异常的语句:
current = float(input('- Current period:'))。 - 异常类型:
ValueError。 - 错误消息:
ValueError: could not convert string to float: "120'"(无法将字符串120'转换为浮点数)。 
由于 float() 无法将字符串 120' 转换为数字,因此 Python 解释器抛出了 ValueError 异常。
在 Python 中,异常具有不同的类型,例如 TypeError、NameError 等。
处理异常
为了让程序更加健壮,你需要在异常发生时对其进行处理。换句话说,你需要捕获异常并通知用户,以便他们能够修复它。
一个好的处理方法是不要显示 Python 解释器返回的内容。相反,你应该用一个更用户友好的消息来替换那个错误消息。
为此,你可以使用 Python 的 try...except 语句:
try:# code that may cause error
except:# handle errors
 
try...except 语句的工作原理如下:
try子句中的语句首先执行。- 如果没有发生异常,则跳过 
except子句,try语句的执行完成。 - 如果 
try子句中的任何语句发生异常,则跳过该子句的其余部分,并执行except子句。 
以下流程图说明了 try...except 语句:
 
 因此,要使用 try...except 语句处理异常,你可以将可能引发异常的代码放在 try 子句中,而将处理异常的代码放在 except 子句中。
以下是如何重写程序并使用 try...except 语句来处理异常的方法:
try:# get input net salesprint('Enter the net sales for')previous = float(input('- Prior period:'))current = float(input('- Current period:'))# calculate the change in percentagechange = (current - previous) * 100 / previous# show the resultif change > 0:result = f'Sales increase {abs(change)}%'else:result = f'Sales decrease {abs(change)}%'print(result)
except:print('Error! Please enter a number for net sales.')
 
如果你再次运行该程序,并输入一个非数字形式的净销售额(值),程序将输出你在 except 块中指定的提示信息;
Enter the net sales for
- Prior period:100
- Current period:120'
Error! Please enter a number for net sales.
 
捕获特定异常
当你将上一期的净销售额输入为零时,你会收到以下信息:
Enter the net sales for
- Prior period:0
- Current period:100
Error! Please enter a number for net sales.
 
在这种情况下,上一期和当期的净销售额都是数字,但程序仍然输出了一条错误信息。这表明一定发生了另一个异常。
try...except 语句允许你处理特定的异常。要捕获选定的异常,你可以在 except 关键字后指定异常的类型:
try:# code that may cause an exception
except ValueError as error:# code to handle the exception
 
例如:
try:# get input net salesprint('Enter the net sales for')previous = float(input('- Prior period:'))current = float(input('- Current period:'))# calculate the change in percentagechange = (current - previous) * 100 / previous# show the resultif change > 0:result = f'Sales increase {abs(change)}%'else:result = f'Sales decrease {abs(change)}%'print(result)
except ValueError:print('Error! Please enter a number for net sales.')
 
当你运行程序并为净销售额输入一个字符串时,你会得到同样的错误信息。
然而,如果你为上一期的净销售额输入零:
Enter the net sales for
- Prior period:0
- Current period:100
 
……你会得到以下错误信息:
Traceback (most recent call last):File "d:/python/try-except.py", line 9, in <module>change = (current - previous) * 100 / previous
ZeroDivisionError: float division by zero
 
这次你遇到了 ZeroDivisionError(零除错误)异常。这个除零异常是由以下语句引起的:
change = (current - previous) * 100 / previous
 
原因是previous为零。
处理多种异常
try...except 结构允许你通过指定多个 except 子句来处理多种异常:
try:# code that may cause an exception
except Exception1 as e1:# handle exception
except Exception2 as e2:# handle exception
except Exception3 as e3:# handle exception 
 
这使你能够针对每种异常类型做出不同的响应。
如果你希望对某些类型的异常做出相同的响应,可以将它们归为一个 except 子句中:
try:# code that may cause an exception
except (Exception1, Exception2):# handle exception
 
以下示例展示了如何使用 try...except 来处理 ValueError 和 ZeroDivisionError 异常:
try:# get input net salesprint('Enter the net sales for')previous = float(input('- Prior period:'))current = float(input('- Current period:'))# calculate the change in percentagechange = (current - previous) * 100 / previous# show the resultif change > 0:result = f'Sales increase {abs(change)}%'else:result = f'Sales decrease {abs(change)}%'print(result)
except ValueError:print('Error! Please enter a number for net sales.')
except ZeroDivisionError:print('Error! The prior net sales cannot be zero.')
 
当为上一期的净销售额输入零时:
Enter the net sales for
- Prior period:0
- Current period:120
 
……你会得到以下错误:
Error! The prior net sales cannot be zero.
 
通过在异常处理列表的末尾放置except Exception来捕获其他一般性错误,是一种良好的做法;
try:# get input net salesprint('Enter the net sales for')previous = float(input('- Prior period:'))current = float(input('- Current period:'))# calculate the change in percentagechange = (current - previous) * 100 / previous# show the resultif change > 0:result = f'Sales increase {abs(change)}%'else:result = f'Sales decrease {abs(change)}%'print(result)
except ValueError:print('Error! Please enter a number for net sales.')
except ZeroDivisionError:print('Error! The prior net sales cannot be zero.')
except Exception as error:print(error)
 
总结
- 使用 Python 的 
try...except语句优雅地处理异常。 - 在 
except块中尽可能使用特定的异常类型。 - 使用 
except Exception语句来捕获其他异常。 
try…except…finally
 
摘要:在本节中,你将学习 Python 的 try...except...finally 语句。
Python try…except…finally 语句介绍
 
try...except 语句允许你在 try 子句中捕获一个或多个异常,并在 except 子句中对每个异常进行处理。
try...except 语句还包含一个可选的子句,称为 finally:
try:# code that may cause exceptions
except:# code that handle exceptions
finally:# code that clean up
 
finally 子句无论是否发生异常都会执行。并且它会在 try 子句以及所有 except 子句执行之后执行。
以下流程图展示了 try...except...finally 子句的执行逻辑:
 
try…except…finally 语句示例
 
以下示例使用了 try...except...finally 语句:
a = 10
b = 0try:c = a / bprint(c)
except ZeroDivisionError as error:print(error)
finally:print('Finishing up.')
 
输出:
division by zero
Finishing up.
 
在此示例中,try 子句引发了 ZeroDivisionError 异常,except 和 finally 子句均会执行。
以下示例中的 try 子句未引发错误。因此,try 和 finally 子句中的所有语句均会执行:
a = 10
b = 2try:c = a / bprint(c)
except ZeroDivisionError as error:print(error)
finally:print('Finishing up.')
 
输出:
5.0
Finishing up.
 
try…finally 语句
 
try...except...finally 语句中的 except 子句是可选的。因此,你可以这样写:
try:# the code that may cause an exception
finally:# the code that always executes
 
通常情况下,当无法处理异常,但希望清理资源(例如关闭已打开的文件)时,会使用该语句。
总结
- 使用 Python 的 
try...except...finally语句,无论是否发生异常,均可执行代码块。 - 使用 
finally子句清理资源,例如关闭文件。 
try…except…else
 
摘要:在本教程中,你将学习如何使用 Python 的 try...except...else 语句。
Python try…except…else 语句介绍
try 语句有一个可选的 else 子句,其语法如下:
try:# code that may cause errors
except:# code that handle exceptions
else:# code that executes when no exception occurs
 
try...except...else 语句的工作原理如下:
- 如果 
try子句中发生异常,Python 会跳过try子句中的其余语句,并执行except语句。 - 如果 
try子句中没有发生异常,则执行else子句。 - 当包含 
finally子句时,else子句会在try子句之后、finally子句之前执行。 
Python try…except…else 语句示例
以下是一些使用 try...except...else 语句的示例。
1) 使用 try…except…else 语句进行流程控制
以下示例说明了如何使用 try...except...else 子句开发一个计算身体质量指数(BMI)的程序。
首先,定义一个根据身高和体重计算 BMI 的函数:
def calculate_bmi(height, weight):""" calculate body mass index (BMI) """return weight / height**2
 
第二,定义另一个用于评估 BMI 的函数:
def evaluate_bmi(bmi):""" evaluate the bmi """if 18.5 <= bmi <= 24.9:return 'healthy'if bmi >= 25:return 'overweight'return 'underweight'
 
第三,定义一个新的 main() 函数,该函数提示用户输入身高和体重,并打印出 BMI 结果:
def main():try:height = float(input('Enter your height (meters):'))weight = float(input('Enter your weight (kilograms):'))except ValueError as error:print('Error! please enter a valid number.')else:bmi = round(calculate_bmi(height, weight), 1)evaluation = evaluate_bmi(bmi)print(f'Your body mass index is {bmi}')print(f'This is considered {evaluation}!')
 
main() 函数使用 try...except...else 语句来控制其流程。如果你输入的身高和体重无法转换为数字,将会引发 ValueError 异常。
如果没有发生异常,else 子句将会执行。它会计算 BMI 指数并显示评估结果。
将所有代码整合在一起:
def calculate_bmi(height, weight):""" calculate body mass index (BMI) """return weight / height**2def evaluate_bmi(bmi):""" evaluate the bmi """if 18.5 <= bmi <= 24.9:return 'healthy'if bmi >= 25:return 'overweight'return 'underweight'def main():try:height = float(input('Enter your height (meters):'))weight = float(input('Enter your weight (kilograms):'))except ValueError as error:print(error)else:bmi = round(calculate_bmi(height, weight), 1)evaluation = evaluate_bmi(bmi)print(f'Your body mass index is {bmi}')print(f'This is considered {evaluation}!')main()
 
2) 使用 Python 的 try…except…else 和 finally 示例
如果 try 子句中没有发生异常,else 子句会在 finally 子句之前执行。
以下示例展示了如何使用 try...except...else...finally 子句:
fruits = {'apple': 10,'orange': 20,'banana': 30
}key = None
while True:try:key = input('Enter a key to lookup:')fruit = fruits[key.lower()]except KeyError:print(f'Error! {key} does not exist.')except KeyboardInterrupt:breakelse:print(fruit)finally:print('Press Ctrl-C to exit.')
 
工作原理:
- 首先,定义一个包含三个元素的 
fruits字典。 - 其次,使用 
while循环反复获取用户输入。循环会在用户按下Ctrl+C时停止。 - 第三,在 
while循环内部使用try...except...else...finally子句。我们使用用户输入在字典中查找元素。 
如果键不存在,会引发 KeyError 异常,except 子句将执行。
如果用户按下 Ctrl+C,会引发 KeyboardInterrupt 异常,执行 break 语句以终止循环。
如果在 fruits 字典中找到了键,程序会打印出找到的元素。
finally 子句总是会执行。它会向用户显示提示,告知他们应按下 Ctrl+C 退出。
总结
- 使用 Python 的 
try...except...else语句可以在发生异常时为程序提供一种控制流程的方式。 - 如果没有在 
try子句中发生异常,else子句将执行。 - 如果是这样,
else子句会在try子句之后、finally子句之前执行。 
