Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any way to prevent a context manager from entering the `with` body?

Tags:

python

I tried this:

@contextmanager
def changed_dir(dirname, msg="nothing to do.."):
    if changed(dirname):
        yield
    else:
        print msg
    return

however when I tried to use it:

with changed_dir("foo/bar"):
    print "something in foo/bar was changed"

I was greeted with:

RuntimeError: generator didn't yield

is there any way to get this to work?

update: many people seem to get stuck on the simplicity of the example. Here is a more complex example illustrating the same point

@contextmanager
def changed_dir(dirname, msg="..."):
    cn = db.get_connection(...)
    try:
        cn.execute("insert ...")
        if changed(dirname):
            cn.execute(...)
            yield
            os.mkdirs(os.path.join('backup', dirname))
            # copy the modified tree.. 
            # etc.
        else:
            cn.execute(...)
            print msg
        cn.commit()
    except:
        cn.rollback()
        # cleanup from mkdirs call...
    finally:
        cn.close()

is in-lining the above still the only solution?

like image 494
thebjorn Avatar asked Dec 05 '25 03:12

thebjorn


1 Answers

Guido's comments in PEP-0343 seems to indicate that this use case is copacetic, and based on the example from the pep I came up with (I looked at the link from @Cyphase's answer, but that seems unnecessarily complicated):

class changed_dir(object):
    class NoChange(ValueError):
        pass

    def __init__(self, dirname, msg="nothing to do"):
        self.dirname = dirname
        self.msg = msg

    def __enter__(self):
        if changed(self.dirname):
            return
        else:
            print self.msg
            raise changed_dir.NoChange()

    def __exit__(self, type, value, traceback):
        return isinstance(value, changed_dir.NoChange)

This seems as simple as most contextmanagers (but not as simple as it would be if I could use the decorator..)

like image 166
thebjorn Avatar answered Dec 07 '25 16:12

thebjorn