33

現在の作業ディレクトリを、decorated関数が呼び出される前の状態に復元するデコレータを作成するにはどうすればよいですか?つまり、を実行する関数でデコレータを使用するとos.chdir()、関数が呼び出された後、cwdは変更されません。

4

4 に答える 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 に答える
32

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 のこのブログ投稿に移動します)

于 2012-12-24T09:38:59.057 に答える
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 に答える