I've tried classes, decorators, and passing the conditional using 'as', as suggested by Michael,  so I disagree that with is not suitable here since I have yet to find a better alternative.  If you want I can give pretty concrete examples in the ways they aren't as good.  Furthermore, I think it could be argued that it makes more sense to be able to safely skip the with body without the user of the with statement having to manually catch the exception themselves.... we don't make people catch the StopIteration exception manually when using iterators...

1)  I can't think of many instances in python where a block of code can not be conditionally executed safely:
     if - obvious
     functions - need to be called
     loops - can have 0 or more iterations
     try/except/finally - even here there is the same notion of the code blocks being conditionally executed, just a bit more scrambled

in my view, the 'with' statement exists just because it is nice sugar for bracketing boilerplate around a block of code, so it might as well do that in the most general, reasonable way.  And I think this behavior is pretty reasonable.    

On Feb 29, 2012, at 06:07 AM, Tal Einat <taleinat@gmail.com> wrote:

On Wed, Feb 29, 2012 at 09:02, Craig Yoshioka <craigyk@me.com> wrote:
> So I've recently been trying to implement something for which I had hoped the 'with' statement would be perfect, but it turns out, won't work because Python provides no mechanism by which to skip the block of code in a with statement.
>
> I want to create some functionality to make it easy too wrap command line programs in a caching architecture.  To do this there are some things that need to happen before and after the wrapped CLI program is called, a try,except,finally version might look like this:
>
> def cachedcli(*args):
>    try:
>        hashedoutput = hashon(args)
>        if iscached():
>            return hashedoutput
>        acquirelock()
>        cli(*args,hashedoutput)
>        iscached(True)
>        return hashedoutput
>    except AlreadyLocked:
>        while locked:
>            wait()
>        return example(*args)
>    finally:
>        releaselock()
>
> the 'with' version would look like
>
> def cachedcli(*args)
>    hashedpath = hashon(args)
>    with cacheon(hashedpath):
>         cli(hashedpath,*args)
>    return hashedpath
>
>
> So obviously the 'with' statement would be a good fit, especially since non-python programmers might be wrapping their CLI programs... unfortunately I can't use 'with' because I can't find a clean way to make the with block code conditional.
>
> PEP377 suggested some mechanics that seemed a bit complicated for getting the desired effect, but I think, and correct me if I'm wrong, that the same effect could be achieved by having the __enter__ function raise a StopIteration that would be caught by the context and skip directly to the __exit__ function.  The semantics of this even make some sense too me, since the closest I've been able to get to what I had hoped for was using an iterator to execute the appropriate code before and after the loop block:
>
> def cachedcli(*args)
>    hashedpath = hashon(args)
>    for _ in cacheon(hashedpath):
>         cli(hashedpath,*args)
>    return hashedpath
>
> this still seems non-ideal to me...

Specifically with regard to caching, I recommend writing a CLI
execution class which implements the caching logic internally.

If you really want to do this with some special syntax sugar, use
decorators, which are good for wrapping functions/methods with
caching.

The "with" statement is IMO not suitable here (and rightfully so).

- Tal Einat