javajythonscripting-languagejython-2.7

When to use cleanup() in Jython


Is it necessary to call cleanup() before close() in a PythonInterpreter in Jython every time?

I've been reading the docs, but I don't find much information about this function. The javadocs don't say anything at all. The closest information I've found is here, in readthedocs, where they explain that a cleanup is necessary in some cases programming with threads, and I'm not even sure they refer to this particular function.

I wonder when I need to call cleanup()... and if the answer is always, then why would they make cleanup() and close() separate functions?


Solution

  • Okay, I've been reading the Jython source code and doing some tests. Here is what I found:

    What cleanup() does: It takes charge of the unhandeled resources, like running threads and files.

    What cleanup() doesn't: Reset the state of the interpreter in any form; imported modules and defined variables are kept.

    The following examples show this behavior:

    Example 1

    Let's import a module, define a variable and open a file.

    PythonInterpreter py = new PythonInterpreter();
    
    String code1 = "import sys;"
            + "a=45;"
            + "f = open('test.txt')";
    String code2 = "print(sys.version_info);"
            + "print(a);"
            + "print(f.closed)";
    
    // first execution
    py.exec(code1);
    py.exec(code2);
    
    // second execution
    py.cleanup();
    py.exec(code2);
    
    py.close()
    

    It outputs

    sys.version_info(major=2, minor=7, micro=2, releaselevel='final', serial=0)
    45
    False
    ------
    sys.version_info(major=2, minor=7, micro=2, releaselevel='final', serial=0)
    45
    True
    

    The module sys and the variables a and f still exist with the same values after the cleanup, but the open file is closed.

    Example 2

    For this, func is a slow function that takes aprox 2 seconds to complete (more than a normal cleanup()).

    PythonInterpreter py = new PythonInterpreter();
    
    String code3 = "from threading import Thread\n"
            + "def func():\n"
            + "  print 'th start'\n"
            + "  for i in range(0,20000000):\n"
            + "    x=i\n"
            + "  print 'th done'\n"
            + "th = Thread(target=func)\n"
            + "th.start()";
    String code4 = "print th.isAlive()\n"
            + "th.join()";
    
    // first execution
    py.exec(code3);
    py.exec(code4);
    System.out.println("------");   
    
    // second execution
    py.exec(code3);
    py.cleanup();
    py.exec(code4);
    
    py.close();
    

    That outputs:

    th start
    True
    th done
    ------
    th start
    th done
    False
    

    In the first execution, the main thread has plenty of time to check if th is alive and print it. In the second one, it always waits for th to finish, meaning that the cleanup() joins the thread somewhere.

    Conclusion

    As @mzjn pointed out, the close() function calls cleanup() and that makes sense, so you never need to call cleanup() before close(). The only case where you could need to call it manually would be if you wanted to continue using the PythonInterpreter but needed to close all open files and join all threads.