python throw_python 之 异常处理

1.什么是异常(what)

异常:不正常的情况

不正常的情况,在程序中,会有两种体现:

l自己造孽:写错代码了!错误也是一种异常;程序都运行不起来!

l程序运行过程中,在某些特定条件下,不合适的数据引起程序出现错误导致程序崩溃

n要求用户输入一个数字,但是用户误操作输入了字符串,在进行类型转换时就会出现错误导致程序崩溃!

why为什么要处理异常:

当程序在运行过程中,由于用户的误操作或者不合适的数据引发的程序错误,让代码自己处理并保证程序的正常执行。而不至于因为错误导致程序崩溃!

提高代码的健壮性!

def div(a, b):

try:

print(a / b)

except ZeroDivisionError:

print("Error: b should not be 0 !!")

except Exception as e:

print("Unexpected Error: {}".format(e))

else:

print('Run into else only when everything goes well')

finally:

print('Always run into finally block.')

# tests

div(2, 0)

div(2, 'bad type')

div(1, 2)

# Mutiple exception in one line

try:

print(a / b)

except (ZeroDivisionError, TypeError) as e:

print(e)

# Except block is optional when there is finally

try:

open(database)

finally:

close(database)

# catch all errors and log it

try:

do_work()

except:

# get detail from logging module

logging.exception('Exception caught!')

# get detail from sys.exc_info() method

error_type, error_value, trace_back = sys.exc_info()

print(error_value)

Raise

总结如下:

except语句不是必须的,finally语句也不是必须的,但是二者必须要有一个,否则就没有try的意义了。

except语句可以有多个,Python会按except语句的顺序依次匹配你指定的异常,如果异常已经处理就不会再进入后面的except语句。

except语句可以以元组形式同时指定多个异常,参见实例代码。

except语句后面如果不指定异常类型,则默认捕获所有异常,你可以通过logging或者sys模块获取当前异常。

如果要捕获异常后要重复抛出,请使用raise,后面不要带任何参数或信息。

不建议捕获并抛出同一个异常,请考虑重构你的代码。

不建议在不清楚逻辑的情况下捕获所有异常,有可能你隐藏了很严重的问题。

尽量使用内置的异常处理语句来替换try/except语句,比如with语句,getattr()方法。

如果你需要自主抛出异常一个异常,可以使用raise关键字,等同于C#和Java中的throw语句,其语法规则如下。

raise NameError("bad name!")

raise关键字后面需要指定你抛出的异常类型,一般来说抛出的异常越详细越好,Python在exceptions模块内建了很多的异常类型,通过使用dir()函数来查看exceptions中的异常类型,如下:

import exceptions

# ['ArithmeticError', 'AssertionError'.....]

print dir(exceptions)

自定义异常类型

Python中也可以自定义自己的特殊类型的异常,只需要要从Exception类继承(直接或间接)即可:

class SomeCustomException(Exception):

pass

一般你在自定义异常类型时,需要考虑的问题应该是这个异常所应用的场景。如果内置异常已经包括了你需要的异常,建议考虑使用内置的异常类型。比如你希望在函数参数错误时抛出一个异常,你可能并不需要定义一个InvalidArgumentError,使用内置的ValueError即可。

经验案例

传递异常re-raise Exception

捕捉到了异常,但是又想重新引发它(传递异常),使用不带参数的raise语句即可:

def f1():

print(1/0)

def f2():

try:

f1()

except Exception as e:

raise  # don't raise e !!!

f2()

在Python2中,为了保持异常的完整信息,那么你捕获后再次抛出时千万不能在raise后面加上异常对象,否则你的trace信息就会从此处截断。以上是最简单的重新抛出异常的做法。

还有一些技巧可以考虑,比如抛出异常前对异常的信息进行更新。

def f2():

try:

f1()

except Exception as e:

e.args += ('more info',)

raise

如果你有兴趣了解更多,建议阅读这篇博客。

http://www.ianbicking.org/blo...

使用内置的语法范式代替try/except

Python 本身提供了很多的语法范式简化了异常的处理,比如for语句就处理的StopIteration异常,让你很流畅地写出一个循环。

with语句在打开文件后会自动调用finally中的关闭文件操作。我们在写Python代码时应该尽量避免在遇到这种情况时还使用try/except/finally的思维来处理。

# should not

try:

f = open(a_file)

do_something(f)

finally:

f.close()

# should

with open(a_file) as f:

do_something(f)

再比如,当我们需要访问一个不确定的属性时,有可能你会写出这样的代码:

try:

test = Test()

name = test.name  # not sure if we can get its name

except AttributeError:

name = 'default'

其实你可以使用更简单的getattr()来达到你的目的。

name = getattr(test, 'name', 'default')

最佳实践

最佳实践不限于编程语言,只是一些规则和填坑后的收获。

只处理你知道的异常,避免捕获所有 异常然后吞掉它们。

抛出的异常应该说明原因,有时候你知道异常类型也猜不出所以然的。

避免在catch语句块中干一些没意义的事情。

不要使用异常来控制流程,那样你的程序会无比难懂和难维护。

如果有需要,切记使用finally来释放资源。

如果有需要,请不要忘记在处理异常后做清理工作或者回滚操作。

转载来自:Python技术爱好者

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值