On Nov 6, 11:43 am, Robert Lehmann <[EMAIL PROTECTED]> wrote: > On Thu, 06 Nov 2008 01:02:34 -0800, brasse wrote: > > Hello! > > > I have been running in to some problems when using contextlib.nested(). > > My problem arises when using code similar to this: > > > from __future__ import with_statement > > > from contextlib import nested > > > class Foo(object): > > > def __init__(self, tag, fail=False): > > print 'ctor', tag > > self.tag = tag > > if fail: > > raise Exception() > > > def __enter__(self): > > print '__enter__', self.tag > > return self > > > def __exit__(self, *args): > > print '__exit__', self.tag > > > with nested(Foo('a'), Foo('b', True)) as (a, b): > > print a.tag > > print b.tag > > > Here the construction of b fails which in turn means that the > > contextmanager fails to be created leaving me a constructed object (a) > > that needs to be deconstructed in some way. I realize that nested() is > > in a tight spot here to do anything about it since it doesn't exist. > > This behavior makes it hard for me to use the with statement (using > > nested()) the way I want. > > > Has anyone else been running in to this? Any tips on how to handle > > multiple resources? > > Your problem does not seem to be connected to context managers. The error > occurs before calling `contextlib.nested` at all:: > > >>> foo = [Foo('a')] > ctor a > >>> with nested(*foo) as a: print a > ... > __enter__ a > [<__main__.Foo object at 0x7fbc29408b90>] > __exit__ a > >>> foo = [Foo('a'), Foo('b', True)] > ctor a > ctor b > Traceback (most recent call last): > File "<stdin>", line 1, in <module> > File "<stdin>", line 7, in __init__ > raise Exception() > Exception > > If you need to deconstruct object `a` from your example, your staging is > probably broken. Allocate the resource in `__init__` but only go live > just in `__enter__`. If you do not enter the context, then, you won't > need to deconstruct it as well. > > HTH, > > -- > Robert "Stargaming" Lehmann
Diez, Robert, OK. The practice of "going live" or doing non-trivial initialization in __enter__ is new to me. I'm new to Python with a C++ background, so that shouldn't be a surprise. :-) Ideally I would like to put all initialization in __init__ since then I would be able to use my object right after constructing it, without having to use it in a with statement. The reason I'm struggling with this is probably my C++ background. I'm rally accustomed to design with RAII in mind. Acquiring all resources in the ctor and releasing all resources in the dtor is *really* handy. If you had a class that wanted to acquire some external resources that must be released at some point, how would you rewrite the code from my example? :.:: mattias -- http://mail.python.org/mailman/listinfo/python-list