Reputation: 1486
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?
Upvotes: 2
Views: 2492
Reputation: 10235
sh
now has the pushd()
function that can be used as a context manager to change the current directory temporarily:
import sh
with sh.pushd("/tmp"):
sh.touch("a_file")
See https://amoffat.github.io/sh/sections/command_class.html?highlight=pushd#pushd
Upvotes: 3
Reputation: 94951
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'
Upvotes: 7