Python提供了try、except、else、finally和raise作为处理错误的主要机制。编写可靠的代码意味着预见潜在问题并谨慎处理它们。这些练习将帮助您将错误处理技术应用于常见的编程情境。请记住,目标不仅仅是防止程序崩溃,而且是在事情未按预期进行时提供有益的反馈或采取纠正措施。Exercise 1: Safe Numeric Input通常,您需要从用户那里获取数字输入。然而,用户可能会输入文本、符号或什么都不输入,如果您直接尝试将输入转换为整数或浮点数,这将导致ValueError。任务: 编写一个脚本,要求用户输入他们的年龄。使用try...except块来处理当输入无法转换为整数时发生的ValueError。如果输入无效,打印一条提示消息。如果输入有效,打印一条消息确认他们的年龄。步骤:使用input()函数提示用户输入。使用try块尝试使用int()将输入转换为整数。在try块中,转换成功后,打印确认消息。添加一个except ValueError块,以捕获转换失败时发生的特定错误。在except块中,打印一条错误消息,说明需要有效的整数输入。Example Interaction:请输入您的年龄: thirty 错误:请输入一个有效的整数作为您的年龄。请输入您的年龄: 25 谢谢。您的年龄是 25。Solution:user_input = input("Please enter your age: ") try: age = int(user_input) # 只有当上面的转换成功时,此行代码才会运行 print(f"Thank you. Your age is {age}.") except ValueError: # 如果int()引发ValueError,此代码块将运行 print("Error: Please enter a valid whole number for your age.") 说明: 这种简单的结构是基本的。我们尝试可能失败的操作(int(user_input))。如果成功,try块的其余部分会执行。如果它因为输入不是有效的整数字符串而特别地以ValueError失败,代码会跳到except ValueError块。Exercise 2: Reading from a File Safely与文件系统交互是异常的另一个常见来源。文件可能丢失,或者您可能没有读取它们的权限。任务: 编写一个函数read_file_content(filename),它接受一个文件名作为参数。该函数应尝试打开并读取文件的内容。它应该通过打印特定消息来处理FileNotFoundError。它还应该包含一个finally块,打印一条消息,表明文件读取尝试已完成,无论成功或失败。步骤:定义一个接受filename的函数read_file_content。使用try块,并通过with语句(它会自动处理关闭)以读取模式('r')打开文件。在try块中,读取文件的内容并打印它。添加一个except FileNotFoundError块,打印一条类似“错误:文件'{filename}'未找到。”的消息。添加一个finally块,打印“尝试读取文件完成。”Example Usage:# 假设'my_data.txt'存在并包含“Hello Python!” read_file_content('my_data.txt') # 假设'non_existent_file.txt'不存在 read_file_content('non_existent_file.txt')Expected Output:Hello Python! 尝试读取文件完成。 错误:文件'non_existent_file.txt'未找到。 尝试读取文件完成。Solution:def read_file_content(filename): """ 尝试读取并打印文件的内容。 处理FileNotFoundError,并确保打印最后的消息。 """ try: # 使用'with'确保文件自动关闭 with open(filename, 'r') as file: content = file.read() print("文件内容:") print(content) except FileNotFoundError: print(f"错误:文件'{filename}'未找到。") except Exception as e: # 捕获其他潜在的I/O错误(可选但推荐) print(f"发生了意外错误:{e}") finally: # 此代码块总是执行 print(f"尝试读取'{filename}'完成。") # Example calls print("--- 读取现有文件 ---") # 首先创建一个临时文件用于测试 with open('my_data.txt', 'w') as f: f.write("Hello Python!") read_file_content('my_data.txt') print("\n--- 读取不存在的文件 ---") read_file_content('non_existent_file.txt') # 清理临时文件(可选) import os if os.path.exists('my_data.txt'): os.remove('my_data.txt')说明: with open(...)语句是文件处理的首选,因为它会自动关闭文件,即使发生错误也不例外。try块包含文件操作。FileNotFoundError被专门捕获。finally块保证“尝试完成...”的消息出现,这对于记录日志或确认操作是否已尝试很有用。我们还添加了一个通用的except Exception来捕获其他潜在问题,尽管FileNotFoundError在这里是最常见的。Exercise 3: Calculator with Multiple Error Types and else让我们结合处理多个特定错误和else块。任务: 创建一个函数divide_numbers(numerator, denominator),它尝试执行除法运算。它应该:如果分母为零,处理ZeroDivisionError。如果任一输入不是数字(例如,字符串),处理TypeError。仅当除法成功时,才使用else块打印结果。如果成功则返回结果,如果发生错误则返回None。步骤:定义函数divide_numbers(numerator, denominator)。使用try块计算result = numerator / denominator。添加一个except ZeroDivisionError块,打印“错误:不能除以零。”添加一个except TypeError块,打印“错误:两个输入都必须是数字。”添加一个else块,打印结果(例如,f"结果是 {result}")并返回result。确保如果发生任何异常,函数返回None(如果except块没有return语句,这会隐式发生)。Example Usage:divide_numbers(10, 2) divide_numbers(10, 0) divide_numbers(10, 'a')Expected Output:结果是 5.0 错误:不能除以零。 错误:两个输入都必须是数字。Solution:def divide_numbers(numerator, denominator): """ 将两个数字相除,处理ZeroDivisionError和TypeError。 仅在成功时使用else块打印结果。 如果发生错误,则返回结果或None。 """ try: result = numerator / denominator except ZeroDivisionError: print("Error: Cannot divide by zero.") return None # 发生错误时显式返回 None except TypeError: print("Error: Both inputs must be numbers.") return None # 发生错误时显式返回 None else: # 此代码块仅在try块没有错误地完成时运行 print(f"The result is {result}") return result # Example calls print("--- 有效的除法 ---") divide_numbers(10, 2) print("\n--- 除数为零 ---") divide_numbers(10, 0) print("\n--- 无效的输入类型 ---") divide_numbers(10, 'a')说明: 这展示了处理多个特定错误。else块在这里很重要;它保证只有当try块中的除法在不引发任何捕获的异常的情况下完成时,成功消息和return result语句才会被执行。Exercise 4: Raising an Exception有时,您需要根据程序的逻辑发出错误情况信号,即使Python不会自动引发异常。任务: 编写一个函数calculate_area(length, width)来计算矩形的面积。在开始时添加一个检查:如果length或width中小于或等于零,则引发ValueError,并附带消息“尺寸必须为正数”。否则,计算并返回面积。然后,编写代码在try...except块中调用此函数,以处理潜在的ValueError。步骤:定义函数calculate_area(length, width)。在函数内部,使用if语句检查length <= 0或width <= 0。如果条件为真,使用raise ValueError("尺寸必须为正数")语句。如果条件为假,计算area = length * width并返回它。在函数外部,使用有效输入(例如,5, 10)在try块中调用calculate_area并打印结果。使用无效输入(例如,5, -2)在另一个try块中调用calculate_area。添加一个except ValueError as e块来捕获您的函数引发的异常,并打印e中包含的错误消息。Example Usage:# 使用有效尺寸调用 # 使用无效尺寸调用Expected Output:面积:50 计算面积出错:尺寸必须为正数Solution:def calculate_area(length, width): """ 计算矩形的面积。 如果尺寸非正数,则引发ValueError。 """ if length <= 0 or width <= 0: # 引发异常以指示无效状态 raise ValueError("Dimensions must be positive") # 仅当'if'条件为假时,此代码才运行 area = length * width return area # --- 调用函数并处理潜在错误 --- print("--- 使用有效尺寸计算 ---") try: valid_area = calculate_area(5, 10) print(f"Area: {valid_area}") except ValueError as e: print(f"Error calculating area: {e}") print("\n--- 使用无效尺寸计算 ---") try: invalid_area = calculate_area(5, -2) # 如果引发异常,此print语句将不会被执行 print(f"Area: {invalid_area}") except ValueError as e: # 捕获函数引发的特定错误 print(f"Error calculating area: {e}") 说明: 在这里,calculate_area函数使用raise来强制执行一项规则(正数尺寸)。这向调用该函数代码发出了一个问题信号。调用代码随后使用try...except来捕获这个特定的ValueError并妥善处理,从而防止程序崩溃并告知用户问题所在。引发异常是处理函数前置条件违规或其他逻辑错误的整洁方式。这些练习涵盖了您在Python中使用异常处理的主要方式。通过练习捕获特定错误,使用else和finally,甚至引发自己的异常,您可以编写更可靠和用户友好的程序。