Frage

Wie schreibe ich einem Dekorateur, der das aktuelle Arbeitsverzeichnis wiederherstellt, was es war, bevor die dekorierte Funktion angerufen wurde? Mit anderen Worten, wenn ich den Dekorateur auf einer Funktion verwende, die eine macht os.chdir(), Das CWD wird nicht geändert, nachdem die Funktion aufgerufen wurde.

War es hilfreich?

Lösung

Das path.py Modul (das Sie wirklich verwenden sollten, wenn Sie sich mit Pfaden in Python -Skripten befassen) hat einen Kontextmanager:

subdir = d / 'subdir' #subdir is a path object, in the path.py module
with subdir:
  # here current dir is subdir

#not anymore

(Credits geht an Dieser Blog -Beitrag von Roberto Alsina)

Andere Tipps

Die Antwort auf einen Dekorateur wurde gegeben; Es funktioniert wie angefordert in der Funktionsdefinitionsphase.

Mit Python 2.5+ haben Sie auch die Möglichkeit, dies bei der Funktion zu tun Anruf Stufe mit einem Kontextmanager:

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)

Dies kann bei Bedarf zur Funktionsaufrufzeit verwendet werden:

print "getcwd before:", os.getcwd()
with remember_cwd():
    walk_around_the_filesystem()
print "getcwd after:", os.getcwd()

Es ist eine schöne Option zu haben.

Bearbeiten: Ich habe Fehlerbehandlung hinzugefügt, wie von Codeape vorgeschlagen. Da meine Antwort abgestimmt wurde, ist es fair, eine vollständige Antwort zu geben, alle anderen Probleme beiseite.

Die angegebenen Antworten berücksichtigen nicht, dass die verpackte Funktion eine Ausnahme ausschöpfen kann. In diesem Fall wird das Verzeichnis niemals wiederhergestellt. Der folgende Code fügt den vorherigen Antworten eine Ausnahmebehandlung hinzu.

Als Dekorateur:

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

und als Kontextmanager:

@contextlib.contextmanager
def remember_cwd():
    curdir = os.getcwd()
    try:
        yield
    finally:
        os.chdir(curdir)
def preserve_cwd(function):
   def decorator(*args, **kwargs):
      cwd = os.getcwd()
      result = function(*args, **kwargs)
      os.chdir(cwd)
      return result
   return decorator

So wird es verwendet:

@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
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top