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
子句之前执行。