Python学习笔记——错误处理try

本文深入探讨了Python中的异常处理机制,包括try...except...else结构的使用,如何捕获和处理异常,以及如何通过logging记录错误信息。同时,介绍了自定义异常的创建和抛出,提供了详细的代码示例,帮助读者理解和掌握Python错误处理的最佳实践。

笔记整理于廖雪峰官网和菜鸟教程

错误处理

异常:
Python脚本发生异常时需要捕获处理,否则程序会中止执行。
异常类型:
https://www.runoob.com/python/python-exceptions.html

try…except…else
  • 描述

检测try语块中的错误,except捕获异常信息并处理。
(个人理解)当开始一个try语句后,如果能except错误则继续执行后面的代码,如果没有匹配的except则报错中止。
try:
1、try语句异常,跳回try匹配except,异常处理结束则通过try语句。
2、try语句异常,没有匹配except,异常被递交到上层的try,将结束程序打印错误。
3、try语句没有异常,执行else,通过try语句。
4、无论有无异常,如果存在finally语句,退出try总会执行finally。
except:
1、如果第一个except错误是第二个的父类,那么当出现第二个except对应错误的时候,将被第一个except捕获而不会进行第二个。
2、一个except可以对应多个异常
except(Exception1[, Exception2[,…ExceptionN]]]):
发生以上多个异常中的一个,执行这块代码

a=0
try:
    print('try...')
    r = 10 / int(a)
    print('result:', r)
#如果没有对应错误的except语句,则返回上层调用报错,终止程序,不会输出print('END')
except ValueError as e:
    print('ValueError:', e)
except ZeroDivisionError as e:
    print('ZeroDivisionError:', e)
finally:#无论try中是否有错误都会运行finally
    print('finally...')
print('END')
  • 语法
    try:
    <语句>
    except 异常名1:
    <语句>#引发异常1的处理
    except 异常名2:
    <语句>#引发异常2的处理
    else:
    <语句>#如果没有异常发生
    finally:
    <语句>#退出try总会执行
调用栈

如果错误不能被捕获,就会一直上抛直到被Python解释器捕获。
当程序运行出错一定要分析错误的调用栈信息来定位错误位置。

# err.py:
def foo(s):
    return 10 / int(s)

def bar(s):
    return foo(s) * 2

def main():
    bar('0')

main()

执行结果:
错误是因为调用main(),原因追溯到第9行的bar(‘0’),第6行的foo(s)*2,第三行的return 10/int(s),根据错误类型ZeroDivisionError,int(s)本身并没有出错,但是int(s)返回0,在计算10 / 0时出错,至此,找到错误源头。
$ python3 err.py
Traceback (most recent call last):
File “err.py”, line 11, in
main()
File “err.py”, line 9, in main
bar(‘0’)
File “err.py”, line 6, in bar
return foo(s) * 2
File “err.py”, line 3, in foo
return 10 / int(s)
ZeroDivisionError: division by zero

logging记录错误

使用logging模块,把错误堆栈打印出来记录错误信息,同时继续执行错误。
imort logging
在try语句中
except Exception(错误类型) as e:
logging.exception(e)(打印错误栈)

# err_logging.py

import logging

def foo(s):
    return 10 / int(s)

def bar(s):
    return foo(s) * 2

def main():
    try:
        bar('0')
    except Exception as e:
        logging.exception(e)

main()
print('END')

logging

如果不使用logging,则不会详细记录错误堆栈。

# err_logging.py

import logging

def foo(s):
    return 10 / int(s)

def bar(s):
    return foo(s) * 2

def main():
    try:
        bar('0')
    except Exception as e:
        print('error:',e)

main()
print('END')
#输出
#error: division by zero
#END
raise抛出异常
  • 定义异常
    raise Exception(“Invalid level!”, level)
    错误是class的一个实例,可以通过定义错误类,用raise抛出错误实例。
# err_raise.pyclass FooError(ValueError):
    pass

def foo(s):
    n = int(s)
    if n==0:
        raise FooError('invalid value: %s' % s)
    return 10 / n

foo('0')

执行错误代码后,将追踪到自定义的错误FooError的错误。
$ python3 err_raise.py
Traceback (most recent call last):
File “err_throw.py”, line 11, in
foo(‘0’)
File “err_throw.py”, line 8, in foo
raise FooError(‘invalid value: %s’ % s)
main.FooError: invalid value: 0

  • 抛出异常
    对比以下两段代码,用except捕获错误后,通过raise抛出错误。捕获错误的目的是记录错误,抛出错误是一直向上抛出错误,最终进行处理。
# err_logging.py

import logging

def foo(s):
    return 10 / int(s)

def bar(s):
    return foo(s) * 2

def main():
    try:
        bar('0')
    except Exception as e:
        print('error:',e)

main()
print('END')
#输出
#error: division by zero
#END
# err_reraise.py

def foo(s):
    n = int(s)
    if n==0:
        raise ValueError('invalid value: %s' % s)
    return 10 / n

def bar():
    try:
        foo('0')
    except ValueError as e:
        print('ValueError!')
        raise

bar()
print('end err_reraise')

raise

  • 练习
    运行下面的代码,根据异常信息进行分析,定位出错误源头,并修复:
from functools import reduce

def str2num(s):
    return int(s)

def calc(exp):
    ss = exp.split('+')
    ns = map(str2num, ss)
    return reduce(lambda acc, x: acc + x, ns)

def main():
    r = calc('100 + 200 + 345')
    print('100 + 200 + 345 =', r)
    r = calc('99 + 88 + 7.6')
    print('99 + 88 + 7.6 =', r)

main()

错误信息
100 + 200 + 345 = 645
Traceback (most recent call last):
File “C:\Users\Violette\AppData\Local\Temp\learn_python_4a90wt1w_py\test_6.py”, line 18, in
main()
File “C:\Users\Violette\AppData\Local\Temp\learn_python_4a90wt1w_py\test_6.py”, line 15, in main
r = calc(‘99 + 88 + 7.6’)
File “C:\Users\Violette\AppData\Local\Temp\learn_python_4a90wt1w_py\test_6.py”, line 10, in calc
return reduce(lambda acc, x: acc + x, ns)
File “C:\Users\Violette\AppData\Local\Temp\learn_python_4a90wt1w_py\test_6.py”, line 5, in str2num
return int(s) ValueError: invalid literal for int() with base 10: ’ 7.6’

修改:
本来向直接把int(s)变成float(s),但这样整数的str也将得到float的结果。
看了评论发现,可以这里应用try,将int的错误except生成float。
如果需要完善就是将不能str2num的错误通过except来rasie。

from functools import reduce

def str2num(s):
    try:
        return int(s)
    except:
        return float(s)

#def str2num(s):
   # return int(s)#错误7.6
 #更改为   return float(s)
def calc(exp):
    ss = exp.split('+')
    ns = map(str2num, ss)
    return reduce(lambda acc, x: acc + x, ns)# 错误in str2num return int(s) 

def main():
    r = calc('100 + 200 + 345')
    print('100 + 200 + 345 =', r)
    r = calc('99 + 88 + 7.6')#错误in calc return reduce(lambda acc, x: acc + x, ns) 
    print('99 + 88 + 7.6 =', r)

main()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值