Python try-except 输出难题:同时执行转换与异常
2025-01-21 03:40:56
剖析 try-except 输出问题:同时执行转换与异常处理
在使用 try...except
代码块时,我们可能遇到一种看似矛盾的情况:期望捕获的异常与实际执行的转换代码都同时输出了。这并非异常处理机制失效,而是代码结构与逻辑导致的常见问题。
问题根源
通常情况下,try
语句块内部的某行代码发生异常后,剩余代码理应不再执行。而 except
代码块则会在捕获到特定异常时执行。但出现 “既执行了 try
语句内的操作,又执行了 except
语句”的情况,通常由以下两个原因导致:
-
异常发生前有输出 :如果
try
语句块内、发生异常代码之前,有输出语句(如print
)或其他操作被执行了,那么这些代码的结果自然会出现在最终输出中。因为在异常发生时,这些语句已经完成了。 -
异常发生于函数内部 :当在
try
代码块内调用了一个函数,而这个函数本身并没有自己的异常处理时,函数内引发的异常会被传播回try
代码块,触发外部的except
捕获。 然而,如果函数在引发异常之前有输出,那么这个输出会正常执行,在except
语句执行之后出现在终端。
解决方法
针对上述两种情况,主要采用细化异常捕获,或者添加边界验证方式来避免或妥善处理问题:
方法一:细化异常捕获
当预期会发生特定类型的异常时,应该捕获该特定异常而不是使用通用的 except:
,这样能帮助我们更好地区分不同错误类型并做不同的处理。这让问题查找变得更为高效。比如上文的代码,在option = int(input('Menu Option:'))
这行如果输入了非数字,则会触发ValueError
类型的异常。所以except
应该捕获ValueError
而非是捕获所有异常类型:
def main():
print('What would you like to convert?')
print('1. Miles to Kilometers')
print('2. Fahrenheit to Celcius')
print('3. Gallons to Liters')
print('4. Pounds to Kilograms')
print('5. Inches to Centimeters')
try:
option = int(input('Menu Option:'))
if option == 1:
Inptmiles = float(input('Enter number of miles to convert:'))
milestokm(Inptmiles)
usercontinue()
if option == 2:
InptFrnht = float(input('Enter degrees that you would like to convert:'))
FrnhttoClcs(InptFrnht)
usercontinue()
if option == 3:
InptGllns = float(input('Enter number of Gallons you would like to convert:'))
GllnstoLtrs(InptGlls)
usercontinue()
if option == 4:
InptLbs = float(input('Enter number of pounds you would like to convert:'))
LbstoKgs(InptLbs)
usercontinue()
if option == 5:
InptInches = float(input('Enter number of Inches you would like to convert:'))
InchestoCm(InptInches)
usercontinue()
except ValueError: #捕获具体的ValueError
print('输入错误,请输入有效的数字!')
def milestokm(miles):
convkm = miles * 1.6
print(f'{miles} Miles is equal to {convkm:.2f} Kilometers')
def FrnhttoClcs(Fahrenheit):
convClcs = (Fahrenheit - 32) * 5/9
print(f'{Fahrenheit} Degrees Fahrenheit is equal to {convClcs:.2f} Degrees Celcius')
def GllnstoLtrs(Gallons):
convLtrs = Gallons * 3.9
print(f'{Gallons} Gallons is equal to {convLtrs:.2f} Liters')
def LbstoKgs(Pounds):
convKgs = Pounds * 0.45
print(f'{Pounds} Pounds is equal to {convKgs:.2f} Kilograms')
def InchestoCm(Inches):
convCm = Inches * 2.54
print(f'{Inches} Inches is equal to {convCm:.2f} Centimeters')
def usercontinue():
pass
#实现用户是否继续的函数,这里为了简单,就不实现了
main()
操作步骤:
- 将
except:
改为except ValueError:
。 - 再次运行程序,输入非数字值,仅打印错误信息,转换代码不再执行。
方法二:数据类型与边界验证
在实际应用中,最好先对用户的输入进行类型与边界验证。避免后续转换发生错误。对option
的值添加数字判断以及float
数值边界判断能够确保输入符合预期。比如代码可以修改如下:
def main():
print('What would you like to convert?')
print('1. Miles to Kilometers')
print('2. Fahrenheit to Celcius')
print('3. Gallons to Liters')
print('4. Pounds to Kilograms')
print('5. Inches to Centimeters')
option_input = input('Menu Option:') # 先保存输入的字符串
try:
option = int(option_input) # 对用户输入的字符串做类型转换
except ValueError: # 对字符串转数字失败进行异常处理
print('输入错误,请输入有效的数字选项!')
return
if option < 1 or option > 5: # 判断是否输入的数字是有效的菜单选项
print('请输入 1 到 5 之间的有效选项!')
return
try:
if option == 1:
Inptmiles_str = input('Enter number of miles to convert:') # 获取需要转换的字符串形式
Inptmiles = float(Inptmiles_str) # 把获取的字符串转换成float形式
milestokm(Inptmiles)
usercontinue()
if option == 2:
InptFrnht_str= input('Enter degrees that you would like to convert:')
InptFrnht = float(InptFrnht_str)
FrnhttoClcs(InptFrnht)
usercontinue()
if option == 3:
InptGllns_str= input('Enter number of Gallons you would like to convert:')
InptGllns = float(InptGllns_str)
GllnstoLtrs(InptGllns)
usercontinue()
if option == 4:
InptLbs_str= input('Enter number of pounds you would like to convert:')
InptLbs = float(InptLbs_str)
LbstoKgs(InptLbs)
usercontinue()
if option == 5:
InptInches_str = input('Enter number of Inches you would like to convert:')
InptInches = float(InptInches_str)
InchestoCm(InptInches)
usercontinue()
except ValueError:
print('输入错误,请输入有效的数值!')
def milestokm(miles):
convkm = miles * 1.6
print(f'{miles} Miles is equal to {convkm:.2f} Kilometers')
def FrnhttoClcs(Fahrenheit):
convClcs = (Fahrenheit - 32) * 5/9
print(f'{Fahrenheit} Degrees Fahrenheit is equal to {convClcs:.2f} Degrees Celcius')
def GllnstoLtrs(Gallons):
convLtrs = Gallons * 3.9
print(f'{Gallons} Gallons is equal to {convLtrs:.2f} Liters')
def LbstoKgs(Pounds):
convKgs = Pounds * 0.45
print(f'{Pounds} Pounds is equal to {convKgs:.2f} Kilograms')
def InchestoCm(Inches):
convCm = Inches * 2.54
print(f'{Inches} Inches is equal to {convCm:.2f} Centimeters')
def usercontinue():
pass
main()
操作步骤:
- 将输入获取放到单独的变量里
- 加入对于用户选项输入合法性的判断
- 在类型转换外层添加
try except
语句块。 - 再次运行程序,尝试输入非数字、超出范围的选项或无效数值,观察程序的行为变化。
额外建议
- 记录异常信息: 建议将异常信息记录到日志中,方便后期追踪和调试。
- 提供用户友好的错误信息: 确保用户看到清晰、有指导性的错误信息,而非技术性的异常堆栈。
- 充分的测试: 对于可能出现异常的场景需要编写单元测试。确保这些边界情况得到处理。
通过仔细分析问题、选择合适的异常处理方式,我们可以编写出更为健壮的应用程序,有效地处理异常,避免用户产生不佳的使用体验。