2012-01-10 2 views
3

This bug report утверждает, что интерпретатор Python по состоянию на июнь 2007 года не будет очищать всю выделенную память после вызова Py_Finalize в приложении C/C++ со встроенным интерпретатором Python. Было рекомендовано вызывать Py_Finalize один раз при завершении приложения.Устраняет ли интерпретатор Python 3 встроенную память?

This bug report утверждает, что с версии 3.3 и марта 2011 года интерпретатор все еще теряет память.

Кто-нибудь знает текущее состояние проблемы? Я обеспокоен тем, что у меня есть приложение, в котором интерпретатор вызывается несколько раз для каждого экземпляра, и я испытываю утечку памяти.

Я уже использую boost :: python для обработки подсчетов ссылок, и я очищаю глобальный словарь всех ссылок, созданных при запуске программы Python между прогонами. У меня есть несколько одноэлементных классов - может это проблема?

Является ли это трудной проблемой или это ошибка в интерпретаторе Python?

ответ

4

Вы можете видеть, что ошибка (первая, с 2007 года) закрыта как «wontfix» от nnorwitz, и его сообщение находится в отчете об ошибке.

Почему вы звоните Py_Initialize/Py_Finalize не один раз? Почему бы не сделать что-то вроде этого (я своего рода смешивание C и Python для удобства):

/* startup */ 
Py_Initialize(); 

/* do whatever */ 
while (moreFiles()) { 
    PyRun_SimpleString("execfile('%s')" % nextFile()); 
    /* do whatever */ 
} 

/* shutdown */ 
Py_Finalize(); 

Проблема заключается в том, что большинство людей, которые пишут модули Python не беспокоиться о том, что произойдет, если их модуль завершается и повторно инициализируется, и часто не заботится об очистке во время финализации. Авторы модуля знают, что вся память освобождается при выходе из процесса и не беспокоится ни о чем больше.

Так что это не одна ошибка, это действительно тысячи ошибок - по одному для каждого модуля расширения. Это огромная работа для ошибки, которая затрагивает меньшинство пользователей, большинство из которых имеют жизнеспособное обходное решение.

Вы всегда можете просто опустить вызов Py_Finalize, позвонив по номеру Py_Initialize во второй раз. Это означает, что ваше приложение будет использовать дополнительное использование памяти при первом запуске скрипта Python и что дополнительная память не будет возвращена ОС до выхода. Пока вы все еще используете скрипты Python каждый раз, я бы не классифицировал его как утечку. Ваша заявка может быть не Valgrind-clean, но это лучше, чем утечка, как сито.

Если вам нужно выгрузить ваши (чистые) модули Python, чтобы избежать утечки памяти, вы можете это сделать. Просто удалите их с sys.modules.

Недостатками Py_Finalize: Если выполнение сценариев Python несколько раз, это не имеет особого смысла для запуска Py_Finalize между ними. Вам придется перезагружать все модули каждый раз, когда вы повторно инициализируете; мой Python загружает 28 модулей при загрузке.

Дополнительная информация: Ошибка не ограничивается Python. Значительная часть кода библиотеки на любом языке будет утечка памяти, если вы попытаетесь выгрузить и перезагрузить библиотеки. Многие библиотеки вызывают код C, многие программисты C предполагают, что их библиотеки загружаются один раз и выгружаются при выходе из процесса.

+0

Спасибо, хотя это немного разочаровывает, что нет простого решения. По крайней мере, это подтверждает мой нынешний подход. – user1140116

+0

Что вы пытаетесь достичь? (Часто *, что * можно решить.) –

+0

Я создаю IDE Python, который будет многократно выполнять скрипты python. Каждый раз, когда выполняется сценарий, память, потребляемая программой, увеличивается. Я вызываю Py_Initialize при запуске приложения и никогда не вызываю Py_Finalize (как вызвано boost :: python). Сценарии содержат библиотеки, включая PyOpenGL и PyQt. Я столкнулся с проблемами, в частности, с памятью, которая никогда не освобождается при использовании QImage. – user1140116

Смежные вопросы