Python context managers: son fáciles!
Yo estaba el otro día tratando de hacer cosas de shell scripting con python (como parte de un setup.py monstruo) y me molestaba que en shell es muy fácil hacer esto:
cd foo
bar -baz
cd -
O esto:
pushd foo
bar -baz
popd
O esto:
(cd foo && bar -baz)
Y en python tenia que hacer esto, que es largo y feo:
cwd = os.getcwd()
try:
os.chdir('foo')
os.system('bar -baz')
finally:
os.chdir(cwd)
Cuando en realidad quiero esto:
with os.chdir('foo'):
os.system('bar -baz')
Por supuesto, eso no está. Entonces, pregunté, como se hace eso? Y tuve varias respuestas:
-
Usá Fabric:
with cd("foo"): run("bar")
-
No es difícil:
class DirContextM(object): def __init__(self, new_dir): self.new_dir = new_dir self.old_dir = None def __enter__(self): self.old_dir = os.getcwd() os.chdir(self.new_dir) def __exit__(self, *_): os.chdir(self.old_dir)
-
Es más fácil:
from contextlib import contextmanager @contextmanager def cd(path): old_dir = os.getcwd() os.chdir(path) yield os.chdir(old_dir)
Está bueno, agreguémoslo a path.py path.py
-
Mejor atrapar excepciones:
@contextmanager def cd(path): old_dir = os.getcwd() os.chdir(path) try: yield finally: os.chdir(old_dir)
Aprendí como hacer context managers, sobre contextlib, sobre fabric y sobre path.py. Nada mal para 15 minutos :-)
stackoverflow.com is also useful for such issues:
http://stackoverflow.com/qu...
Used in fabric: http://docs.fabfile.org/en/...
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.
`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`
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.