Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

sh.cd using context manager

here is what I am basically trying to do:

import sh, os

with sh.cd('/tmp'):
  print os.getcwd()

print os.getcwd()

I get the following error though

line 3, in <module>
    with sh.cd('/tmp'):
AttributeError: __exit__

What am I missing here? Are there alternative solutions to change directory within a context?

like image 960
Igor Lankin Avatar asked Aug 19 '26 22:08

Igor Lankin


1 Answers

You can't use just any class/function as a context manager, it has to actually explicitly be implemented that way, using either the contextlib.contextmanager decorator on a function, or in the case of a class, by defining the __enter__ and __exit__ instance methods.

The sh.cd function you're using is simply a wrapper around os.chdir:

>>> import sh
>>> sh.cd
<bound method Environment.b_cd of {}>

b_cd is defined as:

def b_cd(self, path):
    os.chdir(path)

As you can see, it's just a normal function; it can't be used as a context manager.

The link whereswalden provided shows a good way of implementing the behavior you want as a class. It could similarly be implemented as a function like this:

import contextlib
import os

@contextlib.contextmanager
def cd(path):
   old_path = os.getcwd()
   os.chdir(path)
   try:
       yield
   finally:
       os.chdir(old_path)

Sample usage:

print(os.getcwd())
with cd("/"):
    print os.getcwd()
print(os.getcwd())

Output:

'/home/dan'
'/'
'/home/dan'
like image 118
dano Avatar answered Aug 21 '26 12:08

dano