Implementing pushd in python

1.3k views Asked by At

I am trying to understand how the following is an implementation of the Unix command pushd. Specifically what is the purpose of the yield command given that it yields nothing.

@contextmanager
def pushd(path):
    prev = os.getcwd()
    os.chdir(path)
    try:
        yield
    finally:
        os.chdir(prev)

According to wikipedia, 'pushd command saves the current working directory in memory so it can be returned to at any time, optionally changing to a new directory'. What part of this code block performs which functions in this definition?

1

There are 1 answers

0
Andrew On

To understand this code you have to understand why @contextmanager decorator is used. It allows you to use some function in with statement, which will handle a context for you. So you want to do something in some directory and then jump back - your actions will make sense in a context of directory you jumped in. So the use case for this function looks like this:

In [4]: os.chdir('/var')                                                                                                                                                                     

In [5]: os.getcwd()                                                                                                                                                                          
Out[5]: '/var'

In [6]: with pushd('/etc'): 
   ...:     print(os.getcwd()) 
   ...:                                                                                                                                                                                      
/etc

In [7]: os.getcwd()                                                                                                                                                                          
Out[7]: '/var'

As you can see - a directory has changed to /etc inside with block, but after that it has returned to back to /var, resembling popd behavior.

yield in this case is a part of context manager decorator API and it doesn't need to return anything in this case. It is used constructions like

with open('my_file.txt') as file:
   do_something_with_file(file)

where you actually need some resource to work on inside context.

Refer to contextlib documentation to read more about the goals of the module.