Тихий перезапуск интерпретатора Python

У меня есть интерпретатор Python, встроенный в приложение. Приложение долго запускается, и у меня нет возможности перезапустить интерпретатор без перезапуска всего приложения. Что я хотел бы сделать, так это по существу сохранить состояние интерпретатора и легко вернуться в это состояние.

Я начал с сохранения имен всех модулей в sys.modules, с которых запускался интерпретатор python, а затем удаления всех новых модулей из sys.modules по запросу. Похоже, что это подготовило интерпретатор к повторному импорту тех же модулей, даже если он уже импортировал их раньше. Однако это работает не во всех ситуациях, например при использовании одноэлементных классов, статических методов и т. д.

Я бы предпочел не встраивать другой интерпретатор в этот интерпретатор, если этого можно избежать, поскольку будет потеряна простота использования API приложений (а также небольшое снижение скорости, как я полагаю).

Итак, кто-нибудь знает, как я мог бы сохранить состояние интерпретатора, а затем вернуться к нему, чтобы он мог справиться со всеми ситуациями?

Спасибо,

Дэн

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
7
0
5 832
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Одним из очень хакерских и подверженных ошибкам подходов может быть модуль c, который просто копирует память в файл, чтобы его можно было загрузить обратно в следующий раз. Но поскольку я не могу представить, что это всегда будет работать должным образом, может ли травление быть альтернативой?

Если вы можете сделать все свои модули доступными для маринования, тогда вы сможете собрать все в globals (), чтобы его можно было перезагрузить снова.

Если вы заранее знаете, какие модули, классы, функции, переменные и т. д. Используются, вы можете записать их на диск и перезагрузить. Я не уверен, что лучший способ решить эту проблему, если ваша среда содержит много неизвестных. Хотя, возможно, хватит мариновать глобалов и локальных.

Ответ принят как подходящий

Попробуйте этот код из рецептов ActiveState: http://code.activestate.com/recipes/572213/

Он расширяет pickle, поэтому он поддерживает травление всего, что определено в консоли оболочки. Теоретически вы должны просто получить модуль основной в соответствии с их документацией:

import savestate, pickle, __main__
pickle.dump(__main__, open('savestate.pickle', 'wb'), 2)

Это выглядит многообещающе, спасибо, я рассмотрю это немного подробнее.

Dan 11.01.2009 19:57

Не работает для Python 3 в основном из-за изменений модуля pickle, например. pickle.Pickler.dispatch - это нечто иное, и pickle.Pickler.dispatch_table[...] выдаст ошибку при назначении встроенной функции и тому подобное. К сожалению, пока не нашел решения для Py3. :(

Peter Badida 05.09.2018 19:26

Я бы посоветовал устранить первопричину проблемы.

"The application takes a long time to start up and I have no ability to restart the interpreter without restarting the whole application"

Я сомневаюсь, что это на самом деле 100% правда. Если заявка в целом является результатом акта Конгресса, хорошо, ее нельзя изменить. Но если все приложение было написано реальными людьми, то поиск и перемещение кода для перезапуска интерпретатора Python должны быть возможны. Это дешевле, проще и надежнее, чем что-нибудь, иначе вы могли бы решить проблему.

Не в этом случае - приложение является основным программным обеспечением, выпускаемым только один раз в год. Пока эта функция не будет представлена, взлом - единственное доступное решение для ускорения разработки.

Dan 11.01.2009 15:15

Я бы хотел, чтобы мое время так дорого стоило! Это то, что мне придется реализовать за час или два, чтобы попытаться облегчить себе жизнь. Если не получится, продолжим пользоваться существующей системой ...

Dan 11.01.2009 19:54

storing the names of all modules in sys.modules that the python interpreter started with and then deleting all new modules from sys.modules when requested. This appears to make the interpreter prepared to re-import the same modules even though it has already imported them before.

Подход с принудительной перезагрузкой модуля может работать в некоторых обстоятельствах, но это немного сложно. В итоге:

  • Вам необходимо убедиться, что все модули, зависящие друг от друга, перезагружены одновременно. Таким образом, любой модуль 'x', который выполняет 'import y' или 'from y import ...', должен быть удален из sys.modules одновременно с модулем 'y'.

  • Этот процесс потребуется защитить блокировкой, если ваше приложение или любой другой активный модуль использует потоки.

  • Любой модуль, который оставляет хуки, указывающие на себя в других модулях, не может быть повторно загружен, поскольку ссылки на старый модуль останутся в незагруженном / выгружаемом коде. Сюда входят такие вещи, как перехватчики исключений, сигналы, фильтры предупреждений, кодировки, обезьяньи патчи и так далее. Если вы начнете беспечно перезагружать модули, содержащие чужой код, вы можете быть удивлены, как часто они делают подобные вещи, что может привести к незаметным и любопытным ошибкам.

Итак, чтобы заставить его работать, вам необходимо иметь четко определенные границы между взаимозависимыми модулями - «был ли он импортирован при первоначальном запуске», вероятно, недостаточно - и чтобы убедиться, что они хорошо инкапсулированы без неожиданных зависимостей, таких как обезьяна-патч.

Это может быть основано на папке, поэтому, например, что-либо в / home / me / myapp / lib может быть перезагружено как единое целое, оставив другие модули в покое, особенно содержимое stdlib, например. /usr/lib/python2.x/, который, как правило, ненадежно перезагружать. У меня есть код для этого в еще не выпущенной оболочке перезагрузки веб-приложений, если вам нужно.

Ну наконец то:

  • Вам нужно немного узнать о внутреннем устройстве sys.modules, в частности о том, что он оставляет набор значений «None» для обозначения неудачного относительного импорта. Если вы не удалите их одновременно с удалением других значений модуля, последующая попытка импорта модуля может (иногда) закончиться импортом «Нет», что приведет к сбивающим с толку ошибкам.

Это неприятная деталь реализации, которая может изменить и сломать ваше приложение в какой-то будущей версии Python, но это цена за игру с sys.modules неподдерживаемыми способами.

Я думаю, что проблема такого подхода в поддержании состояния. Модуль имеет собственное пространство имен (как и функции и классы внутри него), поэтому любой вызов функции может изменить это состояние. Даже порядок импорта может иметь значение, если модуль запускает код в своем глобальном пространстве имен (при импорте).

Daniel Naab 11.01.2009 05:36

Другие вопросы по теме