如何编写一个恢复当前工作目录的装饰器?
我该怎么写一个装饰器,让它在调用被装饰的函数之前的工作目录恢复到之前的状态?换句话说,如果我在一个会改变当前工作目录的函数上使用这个装饰器,比如用到os.chdir()
,那么在这个函数调用后,当前工作目录就不会被改变。
5 个回答
28
之前的回答没有考虑到被包装的函数可能会出现错误。如果出现错误,目录就永远不会恢复。下面的代码在之前的回答基础上增加了错误处理。
作为一个装饰器:
def preserve_cwd(function):
@functools.wraps(function)
def decorator(*args, **kwargs):
cwd = os.getcwd()
try:
return function(*args, **kwargs)
finally:
os.chdir(cwd)
return decorator
作为一个上下文管理器:
@contextlib.contextmanager
def remember_cwd():
curdir = os.getcwd()
try:
yield
finally:
os.chdir(curdir)
57
关于装饰器的答案已经给出;它在函数定义阶段按要求工作。
从Python 2.5版本开始,你还可以选择在函数调用阶段使用上下文管理器来实现这个功能:
from __future__ import with_statement # needed for 2.5 ≤ Python < 2.6
import contextlib, os
@contextlib.contextmanager
def remember_cwd():
curdir= os.getcwd()
try: yield
finally: os.chdir(curdir)
在函数调用时,如果需要,可以这样使用:
print "getcwd before:", os.getcwd()
with remember_cwd():
walk_around_the_filesystem()
print "getcwd after:", os.getcwd()
这是一种很不错的选择。
编辑:我根据codeape的建议添加了错误处理。因为我的回答得到了点赞,所以提供一个完整的答案是公平的,其他问题暂且不提。