Question

Comment puis-je écrire un décorateur qui restaure le répertoire de travail actuel tel qu'il était avant l'appel de la fonction décorée? En d'autres termes, si j'utilise le décorateur sur une fonction qui effectue un os.chdir () , le cwd ne sera pas modifié après l'appel de la fonction.

Était-ce utile?

La solution

Le module path.py (que vous devriez vraiment utiliser si vous gérez des chemins dans des scripts python ) a un gestionnaire de contexte:

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

#not anymore

(les remerciements vont à ce billet de blog de Roberto Alsina)

Autres conseils

La réponse pour un décorateur a été donnée; cela fonctionne au stade de la définition de la fonction comme demandé.

Avec Python 2.5+, vous avez également la possibilité de le faire à l'étape call à l'aide d'un gestionnaire de contexte:

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)

qui peut être utilisé si nécessaire au moment de l'appel de fonction comme:

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

C'est une bonne option.

EDIT: J'ai ajouté le traitement des erreurs comme suggéré par codeape. Depuis que ma réponse a été votée, il est juste de proposer une réponse complète, toutes les autres questions mises à part.

Les réponses fournies ne tiennent pas compte du fait que la fonction encapsulée peut générer une exception. Dans ce cas, le répertoire ne sera jamais restauré. Le code ci-dessous ajoute la gestion des exceptions aux réponses précédentes.

en tant que décorateur:

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

et en tant que gestionnaire de contexte:

@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

Voici comment il est utilisé:

@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
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top