Skip to main content

Ralsina.Me — Roberto Alsina's website

Python context managers: they are easy!

This comes from this thread in the Python Ar­genti­na mail­ing list (which I strong­ly rec­om­mend if you read span­ish).

I was the oth­er day try­ing to do shel­l-scrip­t-­like-things on python (as part of a mon­ster set­up.py) and I was an­noyed that in shell it's easy to do this:

cd foo
bar -baz
cd -

Or this:

pushd foo
bar -baz
popd

Or this:

(cd foo && bar -baz)

And on Python I had to do this, which is ver­bose and ug­ly:

cwd = os.getcwd()
try:
    os.chdir('foo')
    os.system('bar -baz')
finally:
    os.chdir(cwd)

This is what I want­ed to have:

with os.chdir('foo'):
    os.system('bar -baz')

And of course, you can't do that. So, I asked, how do you im­ple­ment that con­text man­ager? I got sev­er­al an­swer­s.

  1. That's avail­able in Fab­ric:

    with cd("­foo"):
        run("bar")
  2. It's not hard to do:

    class DirCon­textM(ob­jec­t):
        def __init__(­self, new_dir):
            self­.new_dir = new_dir
            self­.old_dir = None
    
        def __en­ter__(­self):
            self­.old_dir = os­.getcwd()
            os­.chdir(­self.new_dir)
    
        def __ex­it__(­self, *_):
            os­.chdir(­self.old_dir)
  3. It's even eas­i­er to do:

    from con­textlib im­port con­textman­ag­er
    
    @con­textman­ag­er
    def cd(­path):
        old_dir = os­.getcwd()
        os­.chdir(­path)
        yield
        os­.chdir(old_dir)
  4. That's cool, so let's add it to path.py

  5. Maybe check for ex­­cep­­tions

    @con­textman­ag­er
    def cd(­path):
        old_dir = os­.getcwd()
        os­.chdir(­path)
        try:
            yield
        fi­nal­ly:
            os­.chdir(old_dir)

All in al­l, I learned how to do con­text man­ager­s, about con­textlib, about fab­ric and about path.py. Which is not bad for 15 min­utes :-)

Χρήστος Γεωργίου / 2012-01-08 11:26:

stackoverflow.com is also useful for such issues:

http://stackoverflow.com/qu...

fungusakafungus / 2012-01-08 13:12:
Vasiliy Faronov / 2012-01-13 13:04:

I’ve been using the shell for, like, six years, and I’ve never heard of `cd -`. This is going to save me some typing over the next six years. Thank you.

Χρήστος Γεωργίου / 2012-01-13 13:17:

`cd -` is equivalent to `cd $OLDPWD` (the variable is managed by the shell), so you are not restricted to moving back to the previous directory; you can also do stuff like: `mv misplaced-file $OLDPWD`

Phil Romero / 2012-12-18 10:15:

I tend to use the dirstack a little differently. Sometimes cd - can take you strange places. But then again, popd'ing a few directories can also lead you astray.


Contents © 2000-2020 Roberto Alsina