finally 与 atexit 的区别
我最终需要写一些简单的 Python 包装脚本,结构大致是这样的:
try:
code
...
...
except:
raise
finally:
file_handle.close()
db_conn.close()
注意,在 except
块中,我所做的就是把错误信息重新抛给调用这个脚本的地方,没有任何额外的处理;在我的具体情况下,这样做没有问题。这里的想法是,无论有没有错误,清理代码都应该通过 finally
块来执行。
我是不是可以用 atexit
处理器来实现这个目的?这样的话,我就可以省去 try
带来的额外缩进层级。
3 个回答
1
atexit
是在程序结束时被调用的,所以这不是你想要的东西。
4
atexit
模块提供了一个简单的方法,可以注册一些函数,让它们在程序正常关闭时被调用。注册的函数会在解释器正常结束时自动执行。
import atexit
def cleanup():
print 'performimg cleanup'
# multiple functions can be registered here...
atexit.register(cleanup)
另外,sys
模块也有一个功能,叫做sys.exitfunc
,但这里只能注册一个函数。
finally
通常和try except
一起使用,它的功能也可以用来做一些类似清理的工作,不过在finally
块里,sys.exc_info
的值都是None。
如果finally
部分抛出了另一个异常,之前保存的异常会被丢弃。不过你可以在用atexit
注册的函数里加上try except
来处理这些异常。
另一个优缺点是,atexit
注册的函数只会在程序结束时执行,而finally
(配合try-except
)可以在代码的任何地方使用,进行清理工作。
在你的场景中,如果你想在清理内容中抛出异常,使用atexit
会很有帮助,前提是你可以接受清理工作在程序结束时进行。
1
只需使用 contextlib.closing
。
with closing(resource1) as f1, closing(resource2) as f2:
f1.something()
f2.something()
这样它们会自动关闭。文件对象可以直接作为上下文使用,所以你不需要调用 closing
。
如果你的资源不仅仅使用 close
方法,你可以使用 contextlib.contextmanager
装饰器来创建自定义函数。