Огромная утечка памяти при повторных вызовах os.path.isdir?

Я создавал сценарий, связанный с сканированием каталогов, и заметил серьезную утечку памяти при вызове os.path.isdir, поэтому я пробовал следующий фрагмент:

def func(): if not os.path.isdir('D:\Downloads'): return False while True: func() 

В течение нескольких секунд процесс Python достиг 100 МБ ОЗУ.

Я пытаюсь понять, что происходит. Похоже, что огромная утечка памяти действует только тогда, когда путь действительно является допустимым пути к каталогу (это означает, что «return False» не выполняется). Кроме того, интересно посмотреть, что происходит в связанных вызовах, например os.path.isfile.

Мысли?

Редактировать: Я думаю, что на что-то. Хотя isfile и isdir реализованы в модуле genericpath, в системе Windows – isdir импортируется из встроенного nt. Поэтому мне пришлось загрузить источник 2.7.3 (который я должен был сделать давно …).

После небольшого поиска я обнаружил функцию posix__isdir в \ Modules \ posixmodule.c , которая, как я полагаю, является функцией isdir, импортированной из nt.

Эта часть функции (и комментариев) привлекла мое внимание:

 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.

Я только что попробовал свой фрагмент выше с аргументом path в unicode (т.е. u'D: \ Downloads)) – никакой утечки памяти вообще нет. ха-ха.

One Solution collect form web for “Огромная утечка памяти при повторных вызовах os.path.isdir?”

Коренной причиной является отказ вызова PyMem_Free в переменной path в path PyMem_Free от Unicode:

  if (!PyArg_ParseTuple(args, "et:_isdir", Py_FileSystemDefaultEncoding, &path)) return NULL; attributes = GetFileAttributesA(path); if (attributes == INVALID_FILE_ATTRIBUTES) Py_RETURN_FALSE; check: if (attributes & FILE_ATTRIBUTE_DIRECTORY) Py_RETURN_TRUE; else Py_RETURN_FALSE; 

Согласно документации на PyArg_ParseTuple :

  • et : То же, что и es
  • es : PyArg_ParseTuple() выделяет буфер необходимого размера, копирует закодированные данные в этот буфер и корректирует * буфер для ссылки на вновь выделенное хранилище. Вызывающий отвечает за вызов PyMem_Free() для освобождения выделенного буфера после использования .

Это ошибка в стандартной библиотеке Python (исправлена ​​в Python 3 с использованием объектов байтов напрямую); напишите отчет об ошибке на странице http://bugs.python.org .

Python - лучший язык программирования в мире.