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

Dar*_*zer 28 python decorator cwd

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

tzo*_*zot 42

给出了装饰者的答案; 它根据请求在函数定义阶段工作.

使用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)
Run Code Online (Sandbox Code Playgroud)

如果在函数调用时需要,可以使用它:

print "getcwd before:", os.getcwd()
with remember_cwd():
    walk_around_the_filesystem()
print "getcwd after:", os.getcwd()
Run Code Online (Sandbox Code Playgroud)

这是一个不错的选择.

编辑:我添加了codeape建议的错误处理.由于我的答案已经通过,所以提供完整的答案,除了所有其他问题是公平的.


Cha*_*esB 24

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
Run Code Online (Sandbox Code Playgroud)

(来自Roberto Alsina的博客文章)

  • 因为 Daryl Spitzer 假设 `path.py` 与 `pathlib` 相同,所以您也可以假设它们的上下文管理器的行为方式相同,但事实并非如此:`pathlib.Path` 不会触及 CWD,而是起作用作为 `open()` 的上下文管理器(“关闭”潜在打开的文件描述符)。 (5认同)
  • 如果 path.py 现在是内置的,也许您应该回答http://stackoverflow.com/questions/3899761/will-the-real-path-py-please-stand-up。 (2认同)

cod*_*ape 22

给定的答案未考虑到包装函数可能引发异常.在这种情况下,永远不会恢复该目录.下面的代码将异常处理添加到以前的答案中.

作为装饰者:

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
Run Code Online (Sandbox Code Playgroud)

并作为上下文管理器:

@contextlib.contextmanager
def remember_cwd():
    curdir = os.getcwd()
    try:
        yield
    finally:
        os.chdir(curdir)
Run Code Online (Sandbox Code Playgroud)


Mac*_*exa 18

你不需要为你写它。在 python 3.11 中,开发人员已经为您编写了它。在 github.com 上查看他们的代码。

import contextlib
with contextlib.chdir('/path/to/cwd/to'):
    pass
Run Code Online (Sandbox Code Playgroud)