如何编写一个修饰器,将当前工作目录恢复到调用修饰函数之前的状态?换句话说,如果我在执行os.chdir()
的函数上使用装饰器,则在调用函数后不会更改cwd。
答案 0 :(得分:37)
给出了装饰者的答案;它按照要求在函数定义阶段工作。
使用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建议的错误处理。由于我的答案已被否决,所以提供完整的答案,除了所有其他问题是公平的。
答案 1 :(得分:20)
给定的答案未考虑到包装函数可能引发异常。在这种情况下,永远不会恢复该目录。下面的代码将异常处理添加到之前的答案中。
作为装饰者:
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)
答案 2 :(得分:19)
path.py模块(如果处理python脚本中的路径,你真的应该使用它)有一个上下文管理器:
subdir = d / 'subdir' #subdir is a path object, in the path.py module
with subdir:
# here current dir is subdir
#not anymore
(来自Roberto Alsina的this blog post)
答案 3 :(得分: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