Clearing all C ++ objects after python script completes

I have an application that implements a python interpreter, with custom python modules exporting classes. An example C ++ class might look like this:

class MyClass {
    MyClass() { cout << "created" << endl; }
    ~MyClass() { cout << "destroyed" << endl; }
};

The code for executing python scripts looks like this:

namespace bp = boost::python;
bp::dict dict;

try {
    dict = bp::dict(bp::import("__main__").attr("__dict__"));
    bp::exec_file(filename, dict, dict);
} catch (bp::error_already_set &) {
    // dict.clear()
    PyErr_Print();
    PyErr_Clear();
}

The problem is that C ++ objects created from python code are not destroyed immediately after the script completes with an exception. For example, a simple script is executed twice:

import MyModule
myobj = MyModule.MyClass()
assert False

I get ( A ):

// script launched first time
created
// script finished
// script launched second time
created
destroyed
// script finished
// Py_Finalize() is called
destroyed

I want ( B ):

// script launched first time
created
// script finished
destroyed
// script launched second time
created
// script finished
destroyed
// Py_Finalize() is called

Now, the fun part. If we uncomment // dict.clear(), the behavior starts to change depending on the structure of the script. For the above python snippet, I get output B (as expected), but I still get A for the script as:

import MyModule

def main():
    myobj = MyModule.MyClass()
    assert False

if __name__ == "__main__":
    main()

++, python?

+4

Source: https://habr.com/ru/post/1691084/


All Articles