Pregunta

¿Cómo escribo un decorador que restaura el directorio de trabajo actual a lo que era antes de que se llamara la función decorada? En otras palabras, si uso el decorador en una función que hace un os.chdir () , el cwd no se cambiará después de llamar a la función.

¿Fue útil?

Solución

El módulo path.py (que realmente debería usar si se trata de rutas en scripts de Python ) tiene un administrador de contexto:

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

#not anymore

(los créditos van a esta publicación de blog de Roberto Alsina)

Otros consejos

La respuesta para un decorador ha sido dada; Funciona en la etapa de definición de la función según lo solicitado.

Con Python 2.5+, también tiene la opción de hacerlo en la etapa call utilizando un administrador de contexto:

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)

que puede usarse si es necesario en el tiempo de llamada de función como:

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

Es una buena opción para tener.

EDITAR: Agregué el manejo de errores según lo sugerido por codeape. Dado que mi respuesta ha sido votada, es justo ofrecer una respuesta completa, dejando a un lado todas las demás cuestiones.

Las respuestas dadas no tienen en cuenta que la función envuelta puede generar una excepción. En ese caso, el directorio nunca será restaurado. El código a continuación agrega el manejo de excepciones a las respuestas anteriores.

como decorador:

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

y como gestor de contexto:

@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

Así es como se usa:

@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
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top