Перезагрузка сабмодулей в IPython
Я работаю над проектом на Python, который содержит подмодули и использует библиотеки NumPy и SciPy. В качестве интерактивной консоли я использую IPython. Однако меня не устраивает текущий рабочий процесс, и я хотел бы получить советы по улучшению.
В IPython фреймворк загружается простой командой import
. Однако часто возникает необходимость изменить код в одном из подмодулей фреймворка. На этом этапе модель уже загружена, и я использую IPython для взаимодействия с ней.
Проблема в том, что фреймворк содержит множество взаимосвязанных модулей, т.е. когда фреймворк сначала загружается, главный модуль импортирует и настраивает подмодули. Изменения в коде выполняются только в том случае, если модуль перезагружается с помощью reload(main_mod.sub_mod)
. Этот процесс довольно утомителен, так как мне нужно перезагружать все измененные модули индивидуально, используя полный путь. Было бы очень удобно, если бы команда reload(main_module)
автоматически перезагружала все подмодули, но без перезагрузки NumPy и SciPy.
Есть ли способ оптимизировать этот процесс в IPython?
5 ответ(ов)
Для того чтобы избежать постоянного ввода тех же магических функций, их можно поместить в скрипт автозагрузки IPython. Для этого создайте файл с суффиксом .py
в каталоге .ipython/profile_default/startup
. Все скрипты Python в этой папке будут загружены в лексическом порядке. Пример содержимого вашего скрипта может выглядеть следующим образом:
from IPython import get_ipython
ipython = get_ipython()
ipython.magic("pylab")
ipython.magic("load_ext autoreload")
ipython.magic("autoreload 2")
Таким образом, все указанные магические команды будут автоматически выполняться при запуске IPython, что существенно упростит вашу работу.
Вот как можно перевести ваш ответ на русский язык в стиле StackOverflow:
Можно использовать следующий код для перезагрузки всех подмодулей рекурсивно:
import inspect
# Необходимо инициализировать с пустым множеством для загруженных модулей
def recursively_reload_all_submodules(module, loaded=None):
if loaded is None:
loaded = set()
for name in dir(module):
member = getattr(module, name)
if inspect.ismodule(member) and member not in loaded:
recursively_reload_all_submodules(member, loaded)
loaded.add(module)
import importlib
importlib.reload(module)
import mymodule
recursively_reload_all_submodules(mymodule, set())
Этот код эффективно перезагрузит все модули и подмодули, которые вы ему передадите. Вы также можете добавить эту функцию в ваш файл .ipythonrc
, чтобы она загружалась каждый раз при запуске интерпретатора.
Обратите внимание, что для перезагрузки модулей рекомендуется использовать importlib.reload()
, так как это стандартный способ перезагрузки модулей в Python 3.
Моя стандартная практика для перезагрузки модулей заключается в том, чтобы комбинировать оба метода, начиная с открытия IPython
:
from IPython.lib.deepreload import reload
%load_ext autoreload
%autoreload 2
Если загрузить модули до выполнения этих команд, они не будут перезагружены, даже если вы вручную вызовете reload(module_name)
. Однако, я все же иногда сталкиваюсь с необъяснимыми проблемами, когда методы классов не перезагружаются, и я еще не разобрался с их причинами.
Еще один вариант:
$ cat << EOF > ~/.ipython/profile_default/startup/50-autoreload.ipy
%load_ext autoreload
%autoreload 2
EOF
Проверено на ipython и ipython3 версии 5.1.0 в Ubuntu 14.04.
Перед импортом ваших модулей добавьте следующие строки, где первая проверяет, загружено ли расширение autoreload:
if 'autoreload' not in get_ipython().extension_manager.loaded:
%load_ext autoreload
%autoreload 2
import sys
.
.
.
Это гарантирует, что расширение autoreload
будет загружено только один раз, что позволяет автоматически перезагружать измененные модули без необходимости перезапускать IPython или Jupyter-ноутбук.
В чем разница между pip и conda?
Как сделать графики Matplotlib отображаемыми внутри IPython-ноутбука?
Как увеличить ширину ячейки в Jupyter/IPython Notebook в браузере?
Как клонировать список, чтобы он не изменялся неожиданно после присваивания?
Ошибка: "'dict' объект не имеет метода 'iteritems'"