![机器学习入门: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=1738945197-03PbVX0eWxdNf42RWOgwX7AuBwYYNiBU-0-22cd6ceb945c8264670935a9baf1d1f4)
Python在运行上面代码时,将执行except
代码块中的print
语句,因为x
和y
的变量类型不兼容。
在本章的前面,你看到过两个字符串相减会引发异常:
![030-04](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/030-04.jpg?sign=1738945197-OgKWc24joKJo1dErMU9MlMvsDkk214qB-0-85cc437075b42d5debaa24733c66e403)
处理异常的一种简单方法是使用try/except
代码块:
![030-05](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/030-05.jpg?sign=1738945197-TQ7qF37BwnJdkUZQ9pEoOQF2tMYmotsF-0-a6df13595d6f03b51aa497586f2556a6)
上述代码的输出如下:
![031-01](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/031-01.jpg?sign=1738945197-IFr4KDOS3pSoc3rhlr8wB4p0xLLJR6Ph-0-b4b81efab945fa6f6b6be702f8ffc6a5)
如你所见,上述的代码块定义了名为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=1738945197-KoTAFuNOfJkrycvXJfg0L8z0ZURchuTb-0-8f777a43e9990f68620581868d2a7363)
清单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=1738945197-qckDPrGjtHWV6tQ9WpTS0ZS4M0HO7pUp-0-ed8364ce262016669b00219eb7815e66)
这种代码块更紧凑,但是你不知道发生了三种错误类型中的哪一种。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=1738945197-Dn8QsKmzYyV3J6yLtB708kf2JPj3SNbi-0-1e20bfdef74bb68717d166748ae54147)
清单1.11的输出如下所示(假设用户输入了单词Dave):
![032-01](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/032-01.jpg?sign=1738945197-HQzZSQgnGsd6GXmahKattSldiWsf9tTv-0-b4eabc98c849b72fb76d1e135bf77409)
清单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=1738945197-KY1OgLMUICaE9r1xrB8CS58X4prGl8L9-0-7e8b5138772da552e4be23670c060c9a)
清单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=1738945197-AUzbpL0aJ2G07zBcVzAICdgGXuaTrTjK-0-2e284f74a8b2b3a62716d9ed032f6eda)
清单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=1738945197-tRSdROlcyEHgv8VVI1oH8eanj6PkSmBu-0-a3241fe73151cf2ac4401202ad1a998e)
现在,按如下所示运行上述脚本:
![033-02](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/033-02.jpg?sign=1738945197-AvlagaZNZhDqmvHDHELMy3FZ0YJFBjSy-0-a41424d494952fed4fad8614b0de2804)
输出结果如下:
![033-03](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/033-03.jpg?sign=1738945197-UZTSgUiui3AVJGw17PQpVLmgyOk7jpfB-0-cee268f4235f7c9a7049aebc99151c9e)
从命令行指定输入值的功能非常有用。例如,假设你有一个自定义Python类,其中包含add
和subtract
方法对一组数字进行加和减。
你可以使用命令行参数来指定对一组数字执行何种方法,如下所示:
![033-04](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/033-04.jpg?sign=1738945197-0mPdKZT2ZABG5xjZvCGH7jTJ1loyrW8D-0-b42a83acb4f11df7789c722cc0ef82a5)
此功能非常有用,因为你可以在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=1738945197-97YzK9JCMP4lzlxoRHZW2yyDi884XVkQ-0-d72be85edf55a5882b6b7e5ac2d03e2a)
代码清单1.14定义了main()
函数,该函数检查命令行形参的数量:如果该值大于等于2,则为变量名分配第二个形参的值(第一个形参为Hello.py
),否则Hello
将作为变量值分配给name
。然后,print
语句打印变量name
的值。
代码清单1.14的最后部分使用条件逻辑来确定是否执行main()
函数。