ディレクトリのスキャンに関係するスクリプトを書いていて、os.path.isdir を呼び出すときに深刻なメモリ リークに気付いたので、次のスニペットを試してみました。
def func():
if not os.path.isdir('D:\Downloads'):
return False
while True:
func()
数秒以内に、Python プロセスは 100MB の RAM に達しました。
私は何が起こっているのかを理解しようとしています。パスが実際に有効なディレクトリ パスである場合にのみ、大量のメモリ リークが発生しているようです (つまり、'return False' が実行されません)。また、関連する呼び出し (os.path.isfile など) で何が起こるかを確認するのも興味深いことです。
考え?
編集: 私は何かに乗っていると思います。isfile と isdir は genericpath モジュールに実装されていますが、Windows システムでは、isdir は組み込みの nt からインポートされています。そのため、2.7.3 のソースをダウンロードする必要がありました (かなり前にダウンロードする必要がありました...)。
少し検索した後、\Modules\posixmodule.cにposix__isdir関数が見つかりました。これは、nt からインポートされた「isdir」関数であると想定しています。
関数のこの部分 (およびコメント) が私の目を引きました。
if (PyArg_ParseTuple(args, "U|:_isdir", &po)) {
Py_UNICODE *wpath = PyUnicode_AS_UNICODE(po);
attributes = GetFileAttributesW(wpath);
if (attributes == INVALID_FILE_ATTRIBUTES)
Py_RETURN_FALSE;
goto check;
}
/* Drop the argument parsing error as narrow strings
are also valid. */
PyErr_Clear();
それはすべて、Unicode/ASCII 処理のバグに要約されるようです。
上記のスニペットを unicode のパス引数 (つまり u'D:\Downloads') で試してみたところ、メモリ リークはまったくありませんでした。ハハ。