[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