![机器学习入门:Python语言实现](https://wfqqreader-1252317822.image.myqcloud.com/cover/84/41787084/b_41787084.jpg)
1.4 Python中的异常处理
与JavaScript不同,你无法在Python中将一个数字和一个字符串相加。但你可以使用Python中的try/except
结构检测到非法操作,这类似于JavaScript和Java等语言中的try/catch
结构。
try/except
的代码块示例如下:
![030-03](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/030-03.jpg?sign=1738896605-35qBifO1o9Lh7QvbJzrkzbqErIKV7mu5-0-f45f054a64098c562291d1f3e899ee7a)
Python在运行上面代码时,将执行except
代码块中的print
语句,因为x
和y
的变量类型不兼容。
在本章的前面,你看到过两个字符串相减会引发异常:
![030-04](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/030-04.jpg?sign=1738896605-5FzZuxO6I0N5FkYxnRBTxB6NMnU1PlQ9-0-8110d823cc40d315f49996c72e126c06)
处理异常的一种简单方法是使用try/except
代码块:
![030-05](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/030-05.jpg?sign=1738896605-ssEYZgCQwAQwibGxM26y5u36DWjHJWgB-0-ab9ea7d2ee6204de0e8150b91289e95b)
上述代码的输出如下:
![031-01](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/031-01.jpg?sign=1738896605-eMO5qyTglBiBoYMo6fclLImk92qDj6p2-0-0070027eb0839ea6a3b097722396988c)
如你所见,上述的代码块定义了名为TypeError
的更细粒度的异常,其后跟一个except
代码块,用来处理Python代码执行中可能会发生的所有其他异常。这种风格类似于Java代码中的异常处理。
清单1.10的Exception1.py
说明了如何处理各种类型的异常。
清单1.10 Exception1.py
![031-02](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/031-02.jpg?sign=1738896605-LW5Bk5rWBZuavaxh1VSFElcNUGlLSzJX-0-ae6772866c3e858efdf3ca960af8e1c3)
清单1.10包含一个try
代码块,其后跟三个except
语句。如果try
代码块发生错误,第一个except
语句会与产生的异常类型进行比较。如果存在匹配项,则执行随后的print
语句,然后程序终止。如果不存在匹配项,则对第二个except
语句执行类似的测试。如果两个except
语句都不匹配该异常,则由第三个except
语句处理该异常,会在打印一条消息后“引发”异常。
请注意,你还可以在单个语句中指定多种异常类型,如下所示:
![031-03](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/031-03.jpg?sign=1738896605-17rRPPPR4WYOaG3LUqm7RTAY0ZiVpM1B-0-6866706c5d3acef514333bed90944369)
这种代码块更紧凑,但是你不知道发生了三种错误类型中的哪一种。Python允许自定义异常,但是这部分不在本书的讨论范围之内。
1.4.1 处理用户输入
Python允许通过input()
函数或raw_input()
函数从命令行读取用户输入。一般来说,将用户输入赋值给变量,该变量会包含用户从键盘输入的所有字符。当用户按下<return>
键(包括在输入字符中)时,标志着用户输入结束。清单1.11的UserInput1.py
提示用户输入名称,然后使用该输入作为响应。
清单1.11 UserInput1.py
![031-04](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/031-04.jpg?sign=1738896605-8h9Fxh4foj8eeRN3hGZMTIcPAfxtLCjL-0-ab46fab64d3103557dd81ed22a027944)
清单1.11的输出如下所示(假设用户输入了单词Dave):
![032-01](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/032-01.jpg?sign=1738896605-EvI5kL1acZroEJv9CuiXCQGhfgUDUZtY-0-5526889647db75627193cb7ab19b2480)
清单1.11中的print
语句通过%s
插入字符串,具体字符用%符号后的变量值代替。当具体内容在运行时才能明确时,此功能是十分有用的。
用户输入可能会导致异常(这取决于代码执行的操作),因此代码中包含异常处理是非常重要的。
清单1.12的UserInput2.py
,脚本内容提示用户输入字符串,并尝试在try/except
代码块中将字符串转换为数字。
清单1.12 UserInput2.py
![032-02](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/032-02.jpg?sign=1738896605-6gYtUArwVBVjymCytGw9lYvkt4kiB5kv-0-62ed82e99552aa87574f889b8597f26d)
清单1.12将数字0加到了用户输入的转换为数字的结果中。如果转换成功,则会显示一条带有用户输入的消息。如果转换失败,则expect
代码块中的print
语句会打印一条消息。
注意:此代码示例使用eval()
函数。但其实应避免使用eval()
函数,这样你的代码才不会执行任何强制(可能是破坏性的)命令。
清单1.13的UserInput3.py
脚本内容提示用户输入两个数字,并尝试在一组try/except
代码块中计算其总和。
清单1.13 UserInput3.py
![032-03](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/032-03.jpg?sign=1738896605-0mD7DAtkpEi8LaiEUKnFAegkwWFnPfj6-0-6cbfefb8d011e19494946a603b9fa0d9)
清单1.13包含两个try
代码块,每个try
代码块后面都有一个except
语句。第一个try
代码块尝试将第一个用户提供的数字添加到变量sum
中,第二个try
代码块尝试将第二个用户提供的数字添加到先前输入的数字中。如果其中任何一个输入字符串不是有效数字,则会出现一条错误消息。如果两者都是有效数字,则显示的消息就会包含输入的数字及其总和。请务必阅读前面提到的eval()
函数的警告。
1.4.2 命令行参数
Python提供了一个getopt
模块来解析命令行选项和参数,而Python sys
模块通过sys.argv
可访问任何命令行参数。这提供了两种用途:
sys.argv
显示命令行参数列表。len(sys.argv)
显示命令行参数的数量。
sys.argv[0]
是程序名称,所以如果Python程序名为test.py
,那么它与sys.argv[0]
的值可以匹配。
现在,你可以不用通过提示用户,而直接在命令行上为Python程序提供输入值。
作为例子,考虑如下所示的test.py脚本:
![033-01](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/033-01.jpg?sign=1738896605-0nOG0lRTHN29XllXCyfe7QFWjnrw6Wnf-0-6cb3db6b857e770a7b9fe22cbbe83565)
现在,按如下所示运行上述脚本:
![033-02](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/033-02.jpg?sign=1738896605-MlrQLGPCgKq6Q9FK0RoOhNM0f8uQ4nwX-0-a685fa39db489f4b20df36d6bb38903c)
输出结果如下:
![033-03](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/033-03.jpg?sign=1738896605-o2Uy47PnQWzxFjtZ7lHrMHZUxB5l8Ic7-0-a5ba4e9dcba0e41a9eb8f128b4bd54f9)
从命令行指定输入值的功能非常有用。例如,假设你有一个自定义Python类,其中包含add
和subtract
方法对一组数字进行加和减。
你可以使用命令行参数来指定对一组数字执行何种方法,如下所示:
![033-04](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/033-04.jpg?sign=1738896605-4tZsUE78ApV6dgxdsU4It0wSIWIAngn3-0-64053031b7ceec0cbc4e0574c9d8ce26)
此功能非常有用,因为你可以在Python类中以编程方式执行不同的方法,同时也意味着可以为代码编写单元测试。附录B将会介绍如何创建自定义Python类。
清单1.14的Hello.py
说明了如何使用sys.argv
检查命令行形参的数量。
清单1.14 Hello.py
![033-05](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/033-05.jpg?sign=1738896605-2qBAmIhNEWBWDbrJjjaoza4DhVp4wlJC-0-4e3414ac72cc89ba3814b9ae4b3100d9)
代码清单1.14定义了main()
函数,该函数检查命令行形参的数量:如果该值大于等于2,则为变量名分配第二个形参的值(第一个形参为Hello.py
),否则Hello
将作为变量值分配给name
。然后,print
语句打印变量name
的值。
代码清单1.14的最后部分使用条件逻辑来确定是否执行main()
函数。