[学习笔记] Python【第033讲:异常处理】总结

一、try-except语句

try:

  检测范围

except Exception[as reason]:

  出现异常(Exception)后的处理代码

例1:

try:
    f = open('test.txt') #该文本不存在
    print(f.read())
    f.close()
except OSError:
    print('文件出错啦!')

运行输出:
文件出错啦!

例2:

try:
    f = open('test.txt') #该文档不存在
    print(f.read())
    f.close()
except OSError as reason:
    print('文件出错啦!\n出错原因是:' + str(reason))


运行输出:
文件出错啦!
出错原因是:[Errno 2] No such file or directory: 'test.txt'



try:
    sum = 1 + '1' #该语句出错,只打印该错误,不再往下执行了
    f = open('test.txt')  #该文档不存在
    print(f.read())
    f.close()
except OSError as reason:
    print('文件出错啦!\n出错原因是:' + str(reason))
except TypeError as reason:
    print('类型出错啦!\n出错原因是:' + str(reason))


运行输出:
类型出错啦!
出错原因是:unsupported operand type(s) for +: 'int' and 'str'

 

二、try-finally语句

try:

  检测范围

except Exception[as reason]:

  出现异常(Exception)后的处理代码

finally:

  无论如何都会被执行的代码

例:

try:
    f = open('D:/Program Files/1/32讲/test.txt', 'w', encoding='utf-8')
    print(f.write('存在了'))  #写入了3个字符,运行结果成功返回3
    sum = 1 + '1'  #但是由于该语句出现异常,没有继续向下执行
    f.close()  #导致该文件没有关闭,写入的3个字符一直在缓冲区,一直没有被保存在文件中
except (OSError, TypeError) as reason:
    print('出错啦!\n出错原因是:' + str(reason))

运行输出:
3
出错啦!
出错原因是:unsupported operand type(s) for +: 'int' and 'str'



引入try-finally语句
try:
    f = open('D:/Program Files/1/32讲/test.txt', 'w', encoding='utf-8')
    print(f.write('存在了')) #这3个字符成功写入文件test.txt中
    sum = 1 + '1'
except (OSError, TypeError) as reason:
    print('出错啦!\n出错原因是:' + str(reason))
finally:
    f.close() #引入finally语句,程序在执行完异常语句后,也会继续执行finally语句,这里成功关闭文件完成保存

运行输出:
3
出错啦!
出错原因是:unsupported operand type(s) for +: 'int' and 'str'

三、raise语句:可以自己抛出一个异常

>>> raise ZeroDivisionError
Traceback (most recent call last):
  File "<pyshell#2>", line 1, in <module>
    raise ZeroDivisionError
ZeroDivisionError
>>> raise ZeroDivisionError('除数为0的异常')
Traceback (most recent call last):
  File "<pyshell#3>", line 1, in <module>
    raise ZeroDivisionError('除数为0的异常')
ZeroDivisionError: 除数为0的异常
>>> 

 

测试题:

0. 我们使用什么方法来处理程序中出现的异常?M2_<pA-ox
答:使用 try……except 搭配来捕获处理程序中出现的异常。

1. 一个 try 语句可以和多个 except 语句搭配吗?为什么?1!)`%T3D
答:可以。因为 try 语句块中可能出现多类异常,利用多个 except 语句可以分别捕获并处理我们感兴趣的异常

try:
    sum = 1 + '1'
    f = open('我是一个不存在的文档.txt')
    print(f.read())
    f.close()
except OSError as reason:
    print('文件出错啦T_T\n错误原因是:' + str(reason))
except TypeError as reason:
    print('类型出错啦T_T\n错误原因是:' + str(reason))

2. 你知道如何统一处理多类异常吗?56Jn2W
答:在 except 后边使用小括号“()”把多个需要统一处理的异常括起来:

try:
    int('abc')
    sum = 1 + '1'
    f = open('我是一个不存在的文档.txt')
    print(f.read())
    f.close()
except (OSError, TypeError):
    print('出错啦T_T\n错误原因是:' + str(reason))

3. except 后边如果不带任何异常类,Python 会捕获所有(try 语句块内)的异常并统一处理,但小甲鱼却不建议这么做,你知道为什么吗?xi[aOK=l'
答:因为它会隐藏所有程序员未想到并且未做好准备处理的错误,例如用户输入ctrl+c试图终止程序会被解释为KeyboardInterrupt异常。

4. 如果异常发生在成功打开文件后,Python 跳到 except 语句执行,并没有执行关闭文件的命令(用户写入文件的数据就可能没有保存起来),因此我们需要确保无论如何(就算出了异常退出)文件也要被关闭,我们应该怎么做呢?Djq>7RW=bP
答:我们可以使用 finally 语句来实现,如果 try 语句块中没有出现任何运行时错误,会跳过 except 语句块执行 finally 语句块的内容。h-kc'2
如果出现异常,则会先执行 except 语句块的内容再接着执行 finally 语句块的内容。总之,finally 语句块里的内容就是确保无论如何都将被执行的内容!

5. 请恢复以下代码中马赛克挡住的内容,使得程序执行后可以按要求输出。9@BFXV~J

答:这道题比较考脑瓜,你想到了吗?

try:
    for i in range(3):
        for j in range(3):
            if i == 2:
                raise KeyboardInterrupt
            print(i, j)
except KeyboardInterrupt:
    print('退出啦!')

 

动动手:Powered by bbs.fishc.comwV*QdE@"_{lnT t6H`sS;-IA&N2C

0. 还记得我们第一个小游戏吗?只要用户输入非整型数据,程序立刻就会蹦出不和谐的异常信息然后崩溃。请使用刚学的异常处理方法修改以下程序,提高用户体验。.j7Av`@lw
猜数字小游戏:

import random

secret = random.randint(1, 10)
print('------fishc------')
temp = input('不妨猜一下小甲鱼现在心里想的是哪个数字:')

try:
    guess = int(temp)
except ValueError:
    print('输入错误')
    guess = secret #这里把生成的随机数赋值给用户猜的数,可以直接跳过while循环,输出game over的信息

while guess != secret:
    temp = input('猜错了,请重新输入:')
    guess = int(temp)
    if guess == secret:
        print('yes,your guess is right!')
        print('very good')
    else:
        if guess > secret:
            print('too big')
        else:
            print('too small')
print('game over')


except语句下面为什么还要再跟一句guess = secret?
如果不加guess = secret的话,运行输出就会报错:
------fishc------
不妨猜一下小甲鱼现在心里想的是哪个数字:y
输入错误
Traceback (most recent call last):
  File "D:/Program Files/1/32讲/0831_2.py", line 12, in <module>
    while guess != secret:
NameError: name 'guess' is not defined
报错显示guess未定义,而之前guess = int(temp)已经赋值定义了,why?
这是因为这里用户输入的y是其他类型的数值,而不是数值类型;这导致temp无法被int化,使guess = int(temp)这句就无效了;所以显示guess在except语句里一直未被定义

1. input() 函数有可能产生两类异常:EOFError(文件末尾endoffile,当用户按下组合键 Ctrl+d 产生)和 KeyboardInterrupt(取消输入,当用户按下组合键 Ctrl+c 产生),再次修改上边代码,捕获处理 input() 的两类异常,提高用户体验。;k*1dn-:Ot

import random

secret = random.randint(1, 10)
print('------fishc------')
#temp = input('不妨猜一下小甲鱼现在心里想的是哪个数字:')

try:
    temp = input('不妨猜一下小甲鱼现在心里想的是哪个数字:')
    guess = int(temp)
except (ValueError, EOFError, KeyboardInterrupt):
    print('输入错误')
    guess = secret #这里把生成的随机数赋值给用户猜的数,可以直接跳过while循环,输出游戏结束的信息

while guess != secret:
    #temp = input('猜错了,请重新输入:')
    try:
        temp = input('猜错了,请重新输入:')
        guess = int(temp)
    except (ValueError, EOFError, KeyboardInterrupt):
        print('输入错误')
    if guess == secret:
        print('yes,your guess is right!')
        print('very good')
    else:
        if guess > secret:
            print('too big')
        else:
            print('too small')
print('game over')

2. 尝试一个新的函数 int_input(),当用户输入整数的时候正常返回,否则提示出错并要求重新输入。%[?gvfFR:T
程序实现如图:

def int_input(num):
    while 1:
        try:
            int(num)
            break
        except ValueError:
            print('输入的并不是整数')
            num = input('请输入一个整数:')

num = input('请输入一个整数:')
int_input(num)



def int_input(prompt):
    print(prompt)
    while True:
        try:
            int(input(prompt)) #相当于int(input('请输入一个整数:'))
            break
        except ValueError:
            print('出错,您输入的不是整数!')

int_input('请输入一个整数:')

3. 把文件关闭放在 finally 语句块中执行还是会出现问题,像下边这个代码,当前文件夹中并不存在"My_File.txt"这个文件,那么程序执行起来会发生什么事情呢?你有办法解决这个问题吗?

try:
    f = open('My_File.txt') # 当前文件夹中并不存在"My_File.txt"这个文件T_T
    print(f.read())
except OSError as reason:
    print('出错啦:' + str(reason))
finally:
    f.close()

filnally语句块中报错是由于:执行了f.close()来关闭;然而当文档不存在并未打开时,f.close()反而带来了异常

try:
    f = open('My_File.txt') # 当前文件夹中并不存在"My_File.txt"这个文件T_T
    print(f.read())
except OSError as reason:
    print('出错啦:' + str(reason))
finally:
    print(locals()) #打印显示文件没有打开,if语句判断就不会执行f.close(),不关闭一个没有打开的文件自然不会出错
    if 'f' in locals(): #如果文件对象变量存在当前局部变量符号表的话,说明打开成功
        f.close()

运行输出:
出错啦:[Errno 2] No such file or directory: 'My_File.txt'
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'D:/Program Files/1/32讲/0831_4.py'}
注:字典{}是print(locals())打印的
print(locals()) 可以看到所有变量的名字和值,如果有这个变量,就说明赋值(这里是打开文件)的过程中没有出错

另外:
>>> locals()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'D:/Program Files/1/32讲/0831_4.py'}
>>> x = open('D:/Program Files/1/32讲/test.txt', 'r')
>>> locals()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'D:/Program Files/1/32讲/0831_4.py', 'x': <_io.TextIOWrapper name='D:/Program Files/1/32讲/test.txt' mode='r' encoding='cp936'>}
>>> y = 666
>>> locals()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'D:/Program Files/1/32讲/0831_4.py', 'x': <_io.TextIOWrapper name='D:/Program Files/1/32讲/test.txt' mode='r' encoding='cp936'>, 'y': 666}
>>> 



点击F1按钮,查询locals()
Update and return a dictionary representing the current local symbol table. 
Free variables are returned by locals() when it is called in function blocks, but not in class blocks. 
Note that at the module level, locals() and globals() are the same dictionary.
更新并返回表示当前局部符号表的字典。
自由变量在函数块中调用时由locals()返回,而不是在类块中调用。
注意,在模块级别,locals()和globals()是同一个字典。


locasl()会把当前代码中所有未被回收的自定义变量都自动收集其中,如果变量没有被回收,都会放在这个字典里。
locals() 函数会以字典类型返回当前位置的全部局部变量,对于函数, 方法, lambda 函式, 类, 它都返回 True。

说人话就是:
locals指令相当于把当前所有能用的上的变量都扔进一个字典里。
该字典里能用上的都留下来了,用不上的(出错的)都被Python给回收了。

I

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值