How do I write a decorator that restores the cwd?
How do I write a decorator that restores the current working directory to what it was before the decorated function was called? In other words, if I use the decorator on a function that does an os.chdir()
, the cwd will not be changed after the function is called.
Asked by: Richard760 | Posted: 28-01-2022
Answer 1
The answer for a decorator has been given; it works at the function definition stage as requested.
With Python 2.5+, you also have an option to do that at the function call stage using a context manager:
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)
which can be used if needed at the function call time as:
print "getcwd before:", os.getcwd()
with remember_cwd():
walk_around_the_filesystem()
print "getcwd after:", os.getcwd()
It's a nice option to have.
EDIT: I added error handling as suggested by codeape. Since my answer has been voted up, it's fair to offer a complete answer, all other issues aside.
Answered by: Catherine951 | Posted: 01-03-2022Answer 2
The path.py module (which you really should use if dealing with paths in python scripts) has a context manager:
subdir = d / 'subdir' #subdir is a path object, in the path.py module
with subdir:
# here current dir is subdir
#not anymore
(credits goes to this blog post from Roberto Alsina)
Answered by: Elise187 | Posted: 01-03-2022Answer 3
The given answers fail to take into account that the wrapped function may raise an exception. In that case, the directory will never be restored. The code below adds exception handling to the previous answers.
as a decorator:
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
and as a context manager:
@contextlib.contextmanager
def remember_cwd():
curdir = os.getcwd()
try:
yield
finally:
os.chdir(curdir)
Answered by: Kristian977 | Posted: 01-03-2022
Answer 4
You dont need to write it for you. With python 3.11, the developers have written it for you. Checkout their code at github.com/python/cpython. Its in module contextlib.
import contextlib
with contextlib.chdir('/path/to/cwd/to'):
pass
Answered by: Lana229 | Posted: 01-03-2022
Answer 5
def preserve_cwd(function):
def decorator(*args, **kwargs):
cwd = os.getcwd()
result = function(*args, **kwargs)
os.chdir(cwd)
return result
return decorator
Here's how it's used:
@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
Answered by: Cherry702 | Posted: 01-03-2022
Similar questions
python - How do I write a async decorator that restores the cwd?
I am trying to create a decorator for an async function that restores cwd. I am using this as a reference: How do I write a decorator that restores the cwd?
This is what I came up with. It's not preserving the cwd, any pointers?
import os
import asyncio
...
python - How do I write a async decorator that restores the cwd?
I am trying to create a decorator for an async function that restores cwd. I am using this as a reference: How do I write a decorator that restores the cwd?
This is what I came up with. It's not preserving the cwd, any pointers?
import os
import asyncio
...
Writing a TTL decorator in Python
I'm trying to write a TTL decorator in python.
Basically I give it raise an exception if the function doesn't
answer in the selected time.
You can find the thead2 snippets on http://sebulba.wikispaces.com/recipe+thread2
from thread2 import Thread
""" A TTL decorator. """
class Worker(Thread):
def __init__(self...
decorator - In Python, is it possible to access the class which contains a method, given only a method object?
I'm pretty new to Python, and haven't been able to find an answer to this question from searching online.
Here is an example decorator that does nothing (yet)
def my_decorator(text):
def wrap(f):
# grab magic f.parent_class_object.my_var and append text
def wrap_f(*args, **kwargs):
f(*args, **kwargs)
return wrap_f
return wrap
Here is an example class
python - A simple freeze behavior decorator
I'm trying to write a freeze decorator for Python.
The idea is as follows :
(In response to the two comments)
I might be wrong but I think there is two main use of
test case.
One is the test-driven development :
Ideally , developers are writing case before writing the code.
It usually helps defining the architecture because this discipline
forces to define the rea...
python - How to return a function value with decorator and thread
have this code
import threading
def Thread(f):
def decorator(*args,**kargs):
print(args)
thread = threading.Thread(target=f, args=args)
thread.start()
thread.join()
decorator.__name__ = f.__name__
return decorator
@Thread
def add_item(a, b):
return a+b
print(add_item(2,2))
but the function never return the value, exits a way to get ...
decorator - Python convert args to kwargs
I am writing a decorator that needs to call other functions prior to call of the function that it is decorating. The decorated function may have positional arguments, but the functions the decorator will call can only accept keyword arguments. Does anyone have a handy way of converting positional arguments into keyword arguments?
I know that I can get a list of the variable names of the decorated function:
Python Decorator 3.0 and arguments to the decorator
I'm excited to see the latest version of the decorator python module (3.0). It looks a lot cleaner (e.g. the syntax is more sugary than ever) than previous iterations.
However, it seems to have lousy support (e.g. "sour" syntax, to horribly stretch the metaphor) for decorators that take arguments themselves. Does anyone have a good example for how you'd cleanly do this using decorator 3....
python - Decorator to mark a method to be executed no more than once even if called several times
I will go straight to the example:
class Foo:
@execonce
def initialize(self):
print 'Called'
>>> f1 = Foo()
>>> f1.initialize()
Called
>>> f1.initialize()
>>> f2 = Foo()
>>> f2.initialize()
Called
>>> f2.initialize()
>>>
I tried to define execonce but could not write one that works with methods.
P...
python - Creating a decorator in a class with access to the (current) class itself
Currently, I'm doing it in this fashion:
class Spam(object):
decorated = None
@classmethod
def decorate(cls, funct):
if cls.decorated is None:
cls.decorated = []
cls.decorated.append(funct)
return funct
class Eggs(Spam):
pass
@Eggs.decorate
def foo():
print "spam and eggs"
print Eggs.decorated # [<function foo at 0x...>]
print Spam.decora...
decorator - Python decorate a class to change parent object type
Suppose you have two classes X & Y. You want to decorate those classes by adding attributes to the class to produce new classes X1 and Y1.
For example:
class X1(X):
new_attribute = 'something'
class Y1(Y):
new_attribute = 'something'
new_attribute will always be the same for both X1 and Y1. X & Y are not related in any meaningful way, except that multiple inhe...
How can I use a class instance variable as an argument for a method decorator in Python?
How can I use a class instance variable as an argument for a method decorator in Python?
The following is a minimal example shows what I'm trying to do. It obviously fails as the decorator function does not have access to the reference to the instance and I have no idea how to get access to the reference from the decorator.
def decorator1(arg1):
def wrapper(function):
print "decorator argument: ...
Still can't find your answer? Check out these communities...
PySlackers | Full Stack Python | NHS Python | Pythonist Cafe | Hacker Earth | Discord Python