Search code examples
pythonlistcode-cleanup

Handling cleanup actions in python by using anonymous function in list


In Python, need to clean up all the actions in reverse order inside finally block.

I will explain the requirment in Perl.

sub fun1{

    add_1();
    verify_1();

    add_2();
    verify_2();

    remove_2();
    remove_1();
}

In case verify_2() throws an exception, add_1() remains uncleaned.

This is how I handle the cleanup in Perl


sub fun1{
@cleanUpActions = ();
try {
   add_1();
   push (@cleanUpActions, sub {remove_1()} );

   verify_1();

   add_2();
   push (@cleanUpActions, sub {remove_2()} );

   verify_2();

   remove_2();
   pop @cleanUpActions;
   remove_1();
   pop @cleanUpActions;

} catch {
   BaseException->throw("")
} finally{
  foreach my $action (reverse @cleanUps){
    &$action;
  }
}

}

Tried the same logic in Python.

def r2():
    remove_2()

def r1():
    remove_1()

clean_list = []

def fun1():
  try:
    add_1()
    clean_list.append(r1)

    verify_1()

    add_2()
    clean_list.append(r2)
    verify_2()


    remove_2();
    clean_list.pop()
    remove_1();
    clean_list.pop()
  except:
     raise Exception
  finally:
     clean_list.reverse()
     for func in clean_list:
         func()

This above Python code works, but its not that I need. Instead of writing separate def , i would like to add the function block as anonymous func into the list, like I can do in Perl. Python Lambda only accepts expression, does not support multi line body.

Is there any other efficient way to handle such cleanup actions in Python.


Solution

  • Anonymous subs are called "lambdas" in Python.

    add_1()
    clean_list.append(lambda: remove_1())
    verify_1()
    

    That said, you can use the name of a function without () as a function pointer.

    >>> def f():
    ...    print("foo")
    ...
    >>> x = f
    >>> x()
    foo
    

    So all you need is

    add_1()
    clean_list.append(remove_1)
    verify_1()
    

    Also note that you can use def inside of a function, allowing you to create a multi-statement cleanup function.

    add_1()
    def r1():
       remove_1()
    clean_list.append(r1)
    verify_1()