如何编写一个装饰器,将当前工作目录恢复到调用装饰函数之前的状态?换句话说,如果我在执行 an 的函数上使用装饰器,os.chdir()
则调用函数后 cwd 将不会更改。
Daryl Spitzer
问问题
16623 次
4 回答
49
已经给出了装饰者的答案;它按要求在函数定义阶段工作。
使用 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的建议添加了错误处理。由于我的答案已被投票通过,因此提供一个完整的答案是公平的,除了所有其他问题。
于 2008-10-03T22:19:30.590 回答
24
给定的答案没有考虑到包装函数可能引发异常。在这种情况下,该目录将永远不会被恢复。下面的代码在前面的答案中添加了异常处理。
作为装饰者:
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)
于 2008-10-04T11:29:33.803 回答
4
def preserve_cwd(function):
def decorator(*args, **kwargs):
cwd = os.getcwd()
result = function(*args, **kwargs)
os.chdir(cwd)
return result
return decorator
以下是它的使用方法:
@preserve_cwd
def test():
print 'was:',os.getcwd()
os.chdir('/')
print 'now:',os.getcwd()
>>> print os.getcwd()
/Users/dspitzer
>>> test()
was: /Users/dspitzer
now: /
>>> print os.getcwd()
/Users/dspitzer
于 2008-10-03T22:06:46.590 回答