10.异常

在本文中将解释有关断言和异常的知识

一、实验目的

  • 断言
  • NameError
  • TypeError
  • 异常处理(try..except)
  • 异常抛出(raise)
  • finally 子句

二、知识要点

1.断言

Python assert(断言)用于判断一个表达式,在表达式条件为 false 的时候触发异常。断言可以在条件不满足程序运行的情况下直接返回错误,而不必等待程序运行后出现崩溃的情况,语法格式为:

1
assert expression

例如我们的代码只能在windows系统下运行,可以先判断当前系统是否符合条件:
1
2
3
import sys
assert ('linux' in sys.platform), '错误'
print("hello")

会输出:
1
2
3
4
5
6
Traceback (most recent call last):
File "F:/Python/10/eg 10-1.py", line 5, in <module>
assert ('linux' in sys.platform), '错误'
AssertionError: 错误

Process finished with exit code 1

当我们将linux更改为win32就会输出hello

2.错误和异常

在程序执行过程中发生的任何错误都是异常。每个异常显示一些相关的错误信息,比如我们在 Python3 中使用 Python2 独有的语法就会发生SyntaxError

1
print 'hello'

输出为:
1
2
3
4
  File "F:/Python/10/eg 10-1.py", line 11
print 'hello'
^
SyntaxError: Missing parentheses in call to 'print'. Did you mean print('hello')?

而如果我们多打了一个空格:
1
print('hello')

就会出现IndentationError
1
2
3
4
5
6
  File "F:/Python/10/eg 10-1.py", line 12
print('hello')
^
IndentationError: unexpected indent

Process finished with exit code 1

接下来将介绍几种常见的异常:
2.1 NameError
当访问一个未定义的变量则会发生 NameError,例如:print(a)会输出:
1
2
3
4
Traceback (most recent call last):
File "F:/Python/10/eg 10-1.py", line 15, in <module>
print(a)
NameError: name 'a' is not defined

2.2 ZeroDivisionError
当把0作为除数则会发生 ZeroDivisionError,例如:print(1/0)会输出:

1
2
3
4
Traceback (most recent call last):
File "F:/Python/10/eg 10-1.py", line 18, in <module>
print(1/0)
ZeroDivisionError: division by zero

2.3 TyprError
当操作或函数应用于不适当类型的对象时引发TyprError,较为常见的是字符串与整数加法,例如:print('1'+1)会输出:

1
2
3
4
Traceback (most recent call last):
File "F:/Python/10/eg 10-1.py", line 21, in <module>
print('1'+1)
TypeError: can only concatenate str (not "int") to str

3.异常处理

异常处理

我将通过一个例子来解释上图的流程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
a = 0
while a != -1:
try:
a = int(input("输入一个数字:"))
if a == -1:
break
except ValueError:
print("输入类型有误")
else:
print(1 + a)
print("输入类型无误")
finally:
print("结束")
print("循环结束")

我们分别输入1a,最后输入-1结束,输出如下:

1
2
3
4
5
6
7
8
9
10
输入一个数字:1
2
输入类型无误
结束
输入一个数字:a
输入类型有误
结束
输入一个数字:-1
结束
循环结束

这个过程是这样的:

  • 如果我们输入一个数字-1,程序停止循环,程序等价为:
1
2
3
4
5
6
7
8
while a != -1:
try:
a = int(input("输入一个数字:"))
if a == -1:
break
finally:
print("结束")
print("循环结束")

注意:finally只要执行了try不管有没有异常都会执行。在真实场景的应用程序中,finally 子句用于释放外部资源(文件或网络连接之类的),无论它们的使用过程中是否出错。

  • 如果我们输入一个字母‘a’,程序异常,程序等价为:
1
2
3
4
5
6
7
8
9
10
while a != -1:
try:
a = int(input("输入一个数字:"))
if a == -1:
break
except ValueError:
print("输入类型有误")
finally:
print("结束")
print("循环结束")

即程序在try中的语句中出现了异常,会在except中匹配对应的异常类型,如果未匹配则会终止程序,如果匹配上对应的异常类型会执行对应except下的语句,如果语句中有fially,在执行完except中的语句会执行fianlly中的语句。

  • 如果我们输入一个整数1,程序无异常,程序等价为:
1
2
3
4
5
6
7
8
9
10
11
while a != -1:
try:
a = int(input("输入一个数字:"))
if a == -1:
break
else:
print(1 + a)
print("输入类型无误")
finally:
print("结束")
print("循环结束")

即程序通过try语句检测之后没有异常,如果是try-except格式,在没有异常的情况下会直接跳出try-except程序块,继续向下执行;如果是try-except-else格式,在没有异常的情况下会进入else语句中的代码;如果是try-except-else-finally格式,在执行完else语句会执行finally语句中的内容。

4.抛出异常

使用raise语句主动抛出异常的意思是开发者可以自己制造程序异常,这里的程序异常不是指发生了内存溢出、列表越界访问等系统异常,而是指程序在执行过程中,发生了用户输入的数据与要求数据不符、用户操作错误等问题,这些问题都需要程序进行处理并给出相应的提示。处理这些问题多使用判断语句,在判断语句体内进行相应的问题处理,如果处理问题的语句过多,就会导致代码复杂化,代码结构不够清晰。在这种情况下,可以使用raise语句主动抛出异常,由异常处理语句块进行处理。例如:

1
2
3
4
5
6
7
8
9
10
11
try:
print("请输入登录账号:")
username = input(">>:")
if username != "zhe":
raise Exception("用户名输入错误")
print("请输入密码:")
psw = input(">>:")
if psw != "123456":
raise Exception("密码输入错误")
except Exception as e:
print(e)

在上述代码中,当我们输入用户名不是zhe时会主动抛出异常用户名输入错误而此时except语句会捕获异常并输出,而如果我们用户名无误,程序会继续向下进行,在密码输入处如果错误会抛出密码输入错误异常,由except捕获之后输出,如果一直无误,程序执行完之后跳出try-except语句。执行下一程序块。

三、实验内容

1.玩转函数

本次挑战中我们将实现一个程序,将分钟转为小时和分钟。在 MinutesToHours.py 文件中实现一个函数 Hours(),将用户输入的 分钟数 转化为 小时数和分钟数,并要求小时数尽量大。将结果以 XX H, XX M 的形式打印出来。

输入:

80

输出:

1 H,20 M

注意:

  • 代码中不要使用 input() 函数。
  • 如果用户输入的是一个负值,程序需要raise 来抛出ValueError 异常。
  • Hours()函数调用的时候,需要使用 try...except 处理异常。获取异常后,在屏幕上打印出Parameter Error 提示用户输入的值有误。
  • 代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import sys


def Hours(minute):
if minute < 0:
raise ValueError("负值")
else:
print("{} H,{} M".format(int(minute / 60), minute % 60))


try:
Hours(int(sys.argv[1]))
except ValueError:
print("Parameter Error")
  • 控制台的输出为:
1
2
(venv) F:\Python\10>python hour.py 70
1 H,10 M

有关sys.argv[]的解释

sys.argv[value]中对于输入的内容实际上保存为了一个列表,列表的第一个元素即为脚本,例如我们写一个输出脚本print_f.py,脚本中的代码如下:

1
2
3
4
import sys

a = sys.argv[0]
print(a)

我们通过控制台在根目录运行,输入:python print_f,敲击回车,会输出print_f
此时我们更改一下脚本中的代码为:

1
2
3
4
import sys

a = sys.argv[1]
print(a)

我们再通过控制台在根目录输入:python print_f hello敲击回车会输出hello
我们再更改一次代码:

1
2
3
4
import sys

a = sys.argv[2:]
print(a)

在控制台中输入:python print_f a b c d e敲击回车输出的为:['b', 'c', 'd', 'e']
通过上面的例子我们容易理解sys.argv的用法。

四、实验结果


下一篇:11.面向对象
上一篇:9.文件处理
目 录:Python学习

本文标题:10.异常

文章作者:小哲

发布时间:2020年03月11日 - 23:48

最后更新:2020年03月30日 - 11:41

原始链接: 点击复制原始链接

许可协议: 协议-转载请保留原文链接及作者