PyWin32 を使用し、Python を再初期化するために Py_Finalize() と Py_Initialize() を時々呼び出すコードがあります。class error
pywintypesの文字列PyRun_String()
( PyWinTypesmodule.cpp 、860 行目) から動的に作成されたクラスが再初期化後に再作成されないというバグが見つかりました。このクラスは、再初期化後に使用されることになり、関数を呼び出そうとすると「NoneType is not callable」エラーがスローされますlen()
。
を呼び出す直前に、上記のリンクと同じソース ファイルにあるPy_Finalize()
PyWinTypes export を呼び出すと、エラーの発生が停止することが確認されています。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;
}
***/
}
}
ここで注目すべき点が 2 つあります。
上部に不思議なコメントがあり、この場合 Python をファイナライズしない理由があることを暗示しています。残念ながら、それが参照している「pycom-dev」メーリング リストはもう存在しないようです。これは問題のスレッドへの正しいリンクだと思いますが、pythonpros.com は sedo ドメイン パーキングのようです。
コメントアウトされた「古いファイナライズ コード」は、Python をファイナライズする前に PyWinGlobals_Free() を呼び出します。ただし、ソース内のこの不可解なコード スニペットを除けば、PyWin32 を使用する場合、Python をファイナライズする前に何か特別なことを行う必要があることを示すドキュメントや情報をウェブ上で見つけることができませんでした。そこで行われる他の呼び出しもあります: FreeGatewayModules() と PyEval_RestoreThread()。これらを自分で呼び出す必要があるかどうかはわかりません。
私たちの修正はうまくいっているようで、それ以上の情報がない場合はおそらく修正を続けるでしょう。