Ir al contenido principal

Ralsina.Me — El sitio web de Roberto Alsina

Python context managers: son fáciles!

Yo es­ta­ba el otro día tra­tan­do de ha­cer co­sas de she­ll scrip­ting con py­thon (co­mo par­te de un se­tu­p.­py mons­truo) y me mo­les­ta­ba que en she­ll es muy fá­cil ha­cer es­to:

cd foo
bar -baz
cd -

O es­to:

pushd foo
bar -baz
popd

O es­to:

(cd foo && bar -baz)

Y en py­thon te­nia que ha­cer es­to, que es lar­go y feo:

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

Cuan­do en rea­li­dad quie­ro es­to:

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

Por su­pues­to, eso no es­tá. En­ton­ce­s, pre­gun­té, co­mo se ha­ce eso? Y tu­ve va­rias res­pues­ta­s:

  1. Usá Fa­­bri­­c:

    wi­th cd("­foo"):
        run("­ba­r")
  2. No es di­­fí­­ci­­l:

    cla­ss Dir­Con­text­M(ob­jec­t):
        def __i­ni­t__(sel­f, new_­di­r):
            se­l­f.­new_­dir = new_­dir
            se­l­f.ol­d_­dir = No­ne
    
        def __en­te­r__(sel­f):
            se­l­f.ol­d_­dir = os.­ge­tcw­d()
            os.­ch­di­r(sel­f.­new_­di­r)
    
        def __e­xi­t__(sel­f, *_):
            os.­ch­di­r(sel­f.ol­d_­di­r)
  3. Es más fá­­ci­­l:

    from con­tex­tlib im­port con­text­ma­na­ger
    
    @con­text­ma­na­ger
    def cd(­pa­th):
        ol­d_­dir = os.­ge­tcw­d()
        os.­ch­di­r(­pa­th)
        yield
        os.­ch­di­r(ol­d_­di­r)
  4. Es­­tá bue­­­no, agre­­gué­­mo­s­­lo a pa­­th.­­py pa­­th.­­py

  5. Me­­jor atra­­par ex­­ce­p­­cio­­­nes:

    @con­text­ma­na­ger
    def cd(­pa­th):
        ol­d_­dir = os.­ge­tcw­d()
        os.­ch­di­r(­pa­th)
        tr­y:
            yield
        fi­na­ll­y:
            os.­ch­di­r(ol­d_­di­r)

Apren­dí co­mo ha­cer con­text ma­na­ger­s, so­bre con­tex­tli­b, so­bre fa­bric y so­bre pa­th.­p­y. Na­da mal pa­ra 15 mi­nu­tos :-)

Χρήστος Γεωργίου / 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