我们有一段使用 PyWin32 的代码,偶尔也会调用 Py_Finalize() 和 Py_Initialize() 来重新初始化 python。我们发现了一个错误,其中有一个动态创建的类 class error,它是从 pywintypes 中使用 PyRun_String() 的字符串创建的(PyWinTypesmodule.cpp,第 860 行) ), 不会在重新初始化后重新创建。此类在重新初始化后最终被使用,并在尝试调用函数 len() 时抛出“NoneType is not callable”错误。
我们观察到,如果在调用 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(),这表明我们的修复可能在正确的轨道上。然而,除了源代码中这段神秘的代码片段之外,我们还没有在网络上找到任何文档或信息表明在使用 PyWin32 时您必须在最终确定 python 之前执行任何特殊操作。那里还有一些其他调用:FreeGatewayModules() 和 PyEval_RestoreThread()。我不确定我们是否应该自己调用这些。
我们的修复似乎有效,在没有任何更多信息的情况下,我们可能会采用它,但最好能得到一些确认。
请您参考如下方法:
答案来自 python-win32 邮件列表:http://mail.python.org/pipermail/python-win32/2013-January/012671.html .
Unfortunately there are a number of problems repeatedly initializing and finalizing Python, hence the code you saw in pywin32 that no longer attempts to support it. The short-story is simply that doing this is not supported using pywin32 (at least until the issues in Python are fixed via the new module API which supports this, and pywin32 is adjusted accordingly)
Mark [Hammond]
