我們有一段使用PyWin32的代碼,偶爾還會調用Py_Finalize()和Py_Initialize()來重新初始化python。我們發現一個錯誤,其中在重新初始化後不會重新創建一個動態創建的類,class error
,該類由在pywintypes(PyWinTypesmodule.cpp,第860行)中具有PyRun_String()
的字符串創建。該類在重新初始化後結束使用,並在嘗試調用函數len()
時拋出「NoneType is callable」錯誤。我應該如何(或者我應該)在PyWin32的存在下完成python?
我們觀察到,如果在調用Py_Finalize()
之前立即調用PyWinTypes輸出PyWinGlobals_Free()
,該輸出位於上面鏈接的相同源文件中,則會停止發生錯誤。
別處在PyWin32代碼庫(在dllmain.cpp),有以下功能,做COM註冊/ unregestration在regsvr32.exe的後清理時被調用:
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()。我不確定我們是否應該自己調用這些。
我們的修復似乎有效,在沒有任何更多信息的情況下,我們可能會使用它,但它會很高興得到一些確認。
您將不得不與PyWin32維護人員討論此問題。這對於SO來說太過本地化了。 –
我在這裏問了一下,因爲似乎沒有任何方法可以用PyWin32獲得支持(參見http://sourceforge.net/projects/pywin32/support?source=navbar)。但是,它聽起來像是http://mail.python.org/mailman/listinfo/python-win32上的pywin32郵件列表可能是最適合它的地方。 – Tom