Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

why is __init__ module in django project loaded twice In the same process?

I'm trying to wrap a c library in a high-level python interface with Boost.Python. One of the client contracts of the c library is that one of the handles can only be allocated once per-process. I was hoping I could enforce this contract on the python side by using a module global.

Here is my django component module's __init__.py. PyGenTL must only be created once per process!

import my_c_mod
import os

print "imager__init__()"
print os.getpid()
ptl = my_c_mod.PyGenTL()

Slightly relevant Boost.Python code

    BOOST_PYTHON_MODULE(my_c_mod)
    {
        using namespace boost::python;

        // Create the Python type object for our extension class and define __init__ function.
        class_<PyGenTL>("PyGenTL")
            .def("sys_info", &PyGenTL::SysInfo)
            .def("list_cameras", &PyGenTL::ListCameras)  // 
            .def("start_camera", &PyGenTL::StartCamera)  // 
        ;
    }

    PyGenTL::PyGenTL()
    {
        try {
            std::cout << "PyGenTL ctor(): allocating GenTL Lib." << std::endl;
            Detail::ThrowError(GCInitLib());
            Detail::ThrowError(TLOpen(&hTL));
        } catch (boost::exception& e) {
            std::cerr << "PyGenTL ERROR! ";
            std::cerr << boost::diagnostic_information(e);
            std::cerr << std::endl;
        }
    }

Note the print statements in the constructor, and os.getpid() in init. Here is the output from the django process. Note that two processes are created at the start of python, which is why two PyGenTLs are created. So far, so good.

C:\work\svn\sw\branches\python\GenTlServer>python manage.py runserver
imager__init__()
2264
PyGenTL ctor(): allocating GenTL Lib.
imager__init__()
2912
PyGenTL ctor(): allocating GenTL Lib.
Validating models...

0 errors found
Django version 1.3, using settings 'GenTlServer.settings'
Development server is running at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.

Now, during page view, __init__ gets called AGAIN within the same process (2912)

imager__init__()
2912
PyGenTL ctor(): allocating GenTL Lib.
ERROR (-1004): Requested module is in use.
PyGenTL ERROR! Requested module is in use.
[23/Jun/2011 18:02:22] "GET / HTTP/1.1" 500 76537

Sure, there is a work around for my particular problem by enforcing the singleton on the C side, but what is the python way to do it?

like image 596
totowtwo Avatar asked Jun 23 '11 23:06

totowtwo


1 Answers

Because it's being loaded via two different entries in sys.path. Be consistent about your imports; I recommend importing the module without going through the project, e.g. import <app>.<module>. Configuring a WSGI container so that you're not dependent on manage.py's mangling of sys.path will help.

like image 116
Ignacio Vazquez-Abrams Avatar answered Nov 13 '22 20:11

Ignacio Vazquez-Abrams