[Python-ideas] Avoiding nested for try..finally: atexit for functions?
Nick Coghlan
ncoghlan at gmail.com
Wed Oct 19 05:58:07 CEST 2011
On Wed, Oct 19, 2011 at 1:14 PM, Chris Rebert <pyideas at rebertia.com> wrote:
> On Tue, Oct 18, 2011 at 7:14 PM, Nikolaus Rath <Nikolaus at rath.org> wrote:
>> Hello,
>>
>> I often have code of the form:
>>
>> def my_fun():
>> allocate_res1()
>> try:
>> # do stuff
>> allocate_res2()
>> try:
>> # do stuff
>> allocate_res3()
>> try:
>> # do stuff
>> finally:
>> cleanup_res3()
>> finally:
>> cleanup_res2()
>> finally:
>> cleanup_res1()
>>
>> return
>>
>> With increasing number of managed resources, the indentation becomes
>> really annoying, there is lots of line noise, and I don't like the fact
>> that the cleanup is so far away from the allocation.
>
> Use the `with` statement and context managers. They were added for
> this exact situation.
> See http://www.python.org/dev/peps/pep-0343/
>
> Resulting code will resemble:
>
> def func():
> with alloc() as res1, alloc() as res2, alloc() as res3:
> # do stuff
Or, to more closely mirror the original example:
# Define these wherever the current resources are defined
@contextlib.contextmanager
def cm1():
res1 = allocate_res1()
try:
yield res1
finally:
cleanup_res1()
@contextlib.contextmanager
def cm2():
res2 = allocate_res2()
try:
yield res2
finally:
cleanup_res2()
@contextlib.contextmanager
def cm3():
res3 = allocate_res3()
try:
yield res2
finally:
cleanup_res3()
def func():
with cm1() as res1:
# do stuff
with cm2() as res2:
# do stuff
with cm3() as res3:
# do stuff
Any time a with statement's body consists solely of another with
statement you can collapse them into one line as Chris did in his
example.
Cheers,
Nick.
--
Nick Coghlan | ncoghlan at gmail.com | Brisbane, Australia
More information about the Python-ideas
mailing list