如何编写恢复cwd的装饰器?

时间:2008-10-03 22:04:01

标签: python decorator cwd

如何编写一个修饰器,将当前工作目录恢复到调用修饰函数之前的状态?换句话说,如果我在执行os.chdir()的函数上使用装饰器,则在调用函数后不会更改cwd。

4 个答案:

答案 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