为什么Django项目中的__init__模块在同一进程中加载两次?
我正在尝试用Boost.Python把一个C语言库封装成一个高级的Python接口。这个C语言库的一个要求是,它的一个句柄在每个进程中只能分配一次。我希望能在Python这边通过使用模块全局变量来强制执行这个要求。
这是我Django组件模块的__init__.py
。PyGenTL
必须在每个进程中只创建一次!
import my_c_mod
import os
print "imager__init__()"
print os.getpid()
ptl = my_c_mod.PyGenTL()
这里有一点相关的Boost.Python代码
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;
}
}
注意构造函数中的打印语句,以及init中的os.getpid()。这是来自Django进程的输出。请注意,在Python启动时会创建两个进程,这就是为什么会创建两个PyGenTL
的原因。到目前为止,一切正常。
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.
现在,在页面视图期间,__init__
在同一个进程(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
当然,我可以通过在C语言那边强制实现单例模式来解决我这个特定的问题,但在Python中应该怎么做呢?
1 个回答
2
因为它是通过两个不同的路径在加载的,路径在 sys.path
里。要保持导入的一致性;我建议你直接导入模块,而不是通过项目来导入,比如用 import <app>.<module>
这种方式。配置一个 WSGI 容器,这样你就不需要依赖 manage.py
对 sys.path
的处理,这样会更好。