异常是在非平凡程序中轻松路由和处理错误的方法。但是一个清晰的概念有助于在程序增长时不要随意破解。(例如,在很远的地方
捕捉内置函数或ing / continue 会很快变得毛茸茸。)ValueError
return
引起的错误之间的主要区别是
- 通过无效/奇怪的用户输入
- 通过错误
- 受动态系统/环境限制。
分离、路由和处理这些错误的合理方法是:
(A) 在可能发生的点附近很早就发现或比较用户输入错误。立即做出反应以进行简单的恢复/重复。否则(用于中断)转换为丰富的异常,该异常可以在调用堆栈的底部或底部(或默认处理程序sys.excepthook
)进一步捕获和区分
(B) 让 bug 异常崩溃到调用堆栈的底部——未处理;或者可能启动舒适的错误演示和反馈操作。
(C) 对于系统环境错误,在 (A) 和 (B) 之间选择一种方法,具体取决于您希望在当前开发阶段出现多少上下文、详细信息和舒适信息。
这样,这可以成为您示例中面向用户的错误处理的可扩展模式:
# Shows scalable user oriented error handling
import sys, traceback
DEBUG = 0
class UserInputError(Exception):
pass
def excercise5():
print("Programming Excercise 5")
print("This program calculates the cost of an order.")
# NOTE: eval() and input() was dangerous
s = input("Enter the weight in pounds: ")
try:
pound = float(s)
except ValueError as ev:
raise UserInputError("Number required for weight, not %r" % s, ev)
if pound < 0:
raise UserInputError("Positive weight required, not %r" % pound)
shippingCost = (0.86 * pound) + 1.50
coffee = (10.50 * pound) + shippingCost
if pound == 1:
print(pound,"pound of coffee costs $", coffee)
else:
print(pound,"pounds of coffee costs $", coffee)
print()
if __name__ == '__main__':
try:
excercise5()
except UserInputError as ev:
print("User input error (please retry):")
print(" ", ev.args[0])
if DEBUG and len(ev.args) > 1:
print(" EXC:", ev.args[1], file=sys.stderr)
except (EnvironmentError, KeyboardInterrupt) as ev:
print("Execution error happend:")
print(" ", traceback.format_exception_only(ev.__class__, ev)[0])
except Exception:
print("Please report this bug:")
traceback.print_exc()