我们有一段使用PyWin32的代码,偶尔会调用Py_Finalize()和Py_Initialize()来重新初始化python。我们发现了一个错误,其中一个动态创建的类class error
是在pywintypes(PyWinTypesmodule.cpp,第860行)中使用PyRun_String()
的字符串创建的,不会在之后重新创建重新初始化。此类最终在重新初始化后使用,并在尝试调用函数len()
时抛出“NoneType不可调用”错误。
我们观察到,如果在调用Py_Finalize()
之前,我们调用PyWinTypes导出PyWinGlobals_Free()
,该错误就会停止发生,该导出位于上面链接的同一源文件中。
在PyWin32代码库的另一个地方(在dllmain.cpp中),有以下函数,在regsvr32.exe中进行COM注册/取消注册后清理时调用:
void PyCom_DLLReleaseRef(void)
{
/*** NOTE: We no longer finalize Python EVER in the COM world
see pycom-dev mailing list archives from April 2000 for why
***/
// Must be thread-safe, although cant have the Python lock!
// only needed when we finalize.
// CEnterLeaveFramework _celf;
LONG cnt = InterlockedDecrement(&g_cLockCount);
// Not optimal, but anything better is hard - g_cLockCount
// could always transition 1->0->1 at some stage, screwing this
// up. Oh well...
if (cnt==0) {
// Send a quit message to the registered thread (if we have one)
if (dwQuitThreadId)
PostThreadMessage(dwQuitThreadId, WM_QUIT, 0, 0);
/*** Old finalize code
if (bDidInitPython) {
PyEval_RestoreThread(ptsGlobal);
PyWinGlobals_Free();
FreeGatewayModule();
Py_Finalize();
bDidInitPython=FALSE;
}
***/
}
}
这里有两件值得注意的事情:
顶部有一个神秘的评论,暗示在这种情况下没有最终确定Python的原因。不幸的是,它所指的“pycom-dev”邮件列表似乎不再存在。我认为this是相关主题的正确链接,但pythonpros.com似乎是一些sedo域名停放的东西。
注释掉的“旧的终结代码”确实在最终化python之前调用了PyWinGlobals_Free(),这表明我们可能正在使用我们的修复程序。但是,除了源代码中这个神秘的代码片段之外,我们还无法在Web上找到任何文档或信息,表明在使用PyWin32时最终确定python之前必须做任何特殊操作。还有一些其他的调用:FreeGatewayModules()和PyEval_RestoreThread()。我不确定我们是否应该自己打电话。
我们的解决方案似乎有效,如果没有更多信息,我们可能会继续使用它,但获得一些确认会很好。
答案 0 :(得分:1)
答案来自python-win32邮件列表:http://mail.python.org/pipermail/python-win32/2013-January/012671.html。
不幸的是,反复初始化有很多问题 最终确定Python,因此你在pywin32中看到的代码不再存在 试图支持它。简短的故事就是这样做 不支持使用pywin32(至少在Python中的问题之前) 通过支持这个的新模块API修复,pywin32是 相应调整)
马克[哈蒙德]