Перезавантаження підмодулів в IPython


363

В даний час я працюю над проектом python, який містить підмодулі та використовує numpy / scipy. Ipython використовується як інтерактивна консоль. На жаль, я не дуже задоволений робочим процесом, яким зараз користуюся, я буду вдячний за пораду.

У IPython фреймворк завантажується простою importкомандою. Однак часто потрібно змінювати код в одному з підмодулів фреймворку. На даний момент модель вже завантажена, і я використовую IPython для взаємодії з нею.

Тепер рамка містить безліч модулів, які залежать один від одного, тобто коли спочатку завантажується рамка, основний модуль імпортує та налаштовує підмодулі. Зміни коду виконуються лише у випадку, якщо модуль перезавантажений за допомогою reload(main_mod.sub_mod). Це громіздко, оскільки мені потрібно перезавантажувати всі змінені модулі окремо, використовуючи повний шлях. Було б дуже зручно, якби ви reload(main_module)також перезавантажили всі підмодулі, але без перезавантаження numpy / scipy ..


Чи хотіли б ви детальніше розглянути детальніше ? However, it is often necessary to change code in one of the submodules of the framework.Чому це так necessary to change code? Спасибі
їжте

16
@eat: Рамка постійно розробляється, тому постійно змінюються бази коду.
Ален

Відповіді:


531

IPython постачається з деяким автоматичним перезавантаженням магією :

%load_ext autoreload
%autoreload 2

Він буде перезавантажувати всі змінені модулі кожного разу перед виконанням нового рядка. Те, як це працює, дещо відрізняється відdreload . Деякі застереження застосовуються, введіть, %autoreload?щоб побачити, що може піти не так.


Якщо ви хочете завжди включати ці налаштування, змініть ваш файл конфігурації IPython ~/.ipython/profile_default/ipython_config.py [1] та додайте:

c.InteractiveShellApp.extensions = ['autoreload']     
c.InteractiveShellApp.exec_lines = ['%autoreload 2']

Кредит до @Kos через коментар нижче.

[1] Якщо у вас немає файлу ~/.ipython/profile_default/ipython_config.py, вам потрібно зателефонувати ipython profile createспочатку. Або файл може бути розташований за адресою $IPYTHONDIR.


63
У мене є c.InteractiveShellApp.extensions = ['autoreload']і c.InteractiveShellApp.exec_lines = ['%autoreload 2']в моїх ~/.ipython/profile_default/ipython_config.py.
Кос

4
Це може бути хітом для продуктивності, тому використовуйте обережно.
асмеурер

3
Перезавантаження виконується лише при натисканні клавіші Enter в оболонку Ipython, і зазвичай не помітно.
пв.

3
Це працює досить добре при налагодженні пакетів, тому яка мета dreload, здається, що завантаження є занадто інвазивним і друкує помилку, коли завантажуються деякі пакети на зразок matplotlib.
тире

3
Якщо ви використовуєте метод @Kos, переконайтеся, що c визначено: c = get_config ()
Tickon

27

У IPython 0,12 (а можливо і раніше) ви можете використовувати це:

%load_ext autoreload
%autoreload 2

Це по суті те саме, що відповідь pv. , за винятком того, що розширення було перейменовано та тепер завантажено за допомогою %load_ext.


20

Чомусь ні %autoreload, ні, dreloadздається, не працюють у ситуації, коли ви імпортуєте код з одного ноутбука в інший . Тільки звичайний Python reloadпрацює:

reload(module)

На основі [1] .


10
У Python 3.4+ ви можете знайти перезавантаження в модулі importlib. Дивіться це питання .
Praveen

1
Цей метод працює при додаванні методу екземпляра на відміну від %autoreloadметодики. Існує відкритий звіт про помилку, щоб додати підтримку до %autoreloadцього. .
ійосеф

18

IPython пропонує dreload()рекурсивно перезавантажувати всі підмодулі. Особисто я вважаю за краще використовувати %run()магічну команду (хоча вона не виконує глибокого перезавантаження, на що в коментарях вказував Джон Салватиє).


11
Я думаю, що (на жаль)% run script.py перезавантажує лише той скрипт, який ви викликаєте, а не пакети, які він імпортує. Якщо ви намагаєтеся налагодити пакет, який ви будуєте, це може бути болем.
Джон Сальватьє

2
NB. dreloadбула замінена в недавньому IPython (наприклад, IPython 6.0) шляхом повторного завантаження .
дан макінлай

8

Модуль з іменем importlibдозволяє отримати доступ до внутрішніх імпортів. Особливо, він забезпечує функцію importlib.reload():

import importlib
importlib.reload(my_module)

Навпаки %autoreload, importlib.reload()також скидайте глобальні змінні, встановлені в модулі. У більшості випадків це те, що ви хочете.

importlibдоступний лише з Python 3.1. Для старшої версії потрібно використовувати модуль imp.


єдине рішення, яке працювало для мене
gustavz

5

http://shawnleezx.github.io/blog/2015/08/03/some-notes-on-ipython-startup-script/

Щоб увімкнути цю магічну функцію знову і знову, їх можна помістити в сценарій запуску 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")

Це також працює, якщо ви запускаєте свій сценарій, наприклад, %run script.pyз IPython REPL
Патрік Санан

3

Як щодо цього:

import inspect

# needs to be primed with an empty set for loaded
def recursively_reload_all_submodules(module, loaded=None):
    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)
    reload(module)

import mymodule
recursively_reload_all_submodules(mymodule, set())

Це повинно ефективно перезавантажити все дерево модулів і підмодулів, які ви їм надаєте. Ви також можете помістити цю функцію у свій .ipythonrc (я думаю), щоб вона завантажувалась кожного разу при запуску перекладача.


Це добре виглядає, однак, можливо, воно не охоплює модулі або члени модулів, які імпортуються за допомогою from ... import ...або import ... as. Принаймні, це доставляє мені часто певних проблем при інтерактивній роботі терміналу. Я перейшов до використання збережених макросів в IPython, які роблять необхідний імпорт та налаштування, щоб почати працювати у заздалегідь визначеному стані.
Бернхард

Це насправді охоплює, from ... import ...і import ... asпоки ви імпортували те, що є імпортом. Єдине, що воно не охоплює - це модулі в пакеті, які не завантажувались із __init__.pyфайлу. Для пакетів ви, ймовірно, можете перевірити, чи є __path__атрибут модуля каталогом. Якщо це так, перейдіть по ньому та рекурсивно імпортуйте всі модулі, які ви могли знайти. Я не писав цю частину, оскільки автор не просив рішення для пакетів.
YH Вонг

Дійсно це виглядає добре. Я подумав над цією можливістю, в той же час я би розраховував, що є якась вбудована функціональність, тобто на основі цього . Однак мені не було зрозуміло, як цим користуватися. Після деякого копання, яке мало відбутися до того, як я опублікував оригінальне запитання, я знайшов це розширення .
Ален

Також ви можете використовувати pkgutilдля отримання всіх підмодулів у пакеті, навіть якщо пакет не імпортує підмодулі у верхній модуль. stackoverflow.com/a/1707786/1243926
оса

Ви також повинні зробити: для модуля вsys.modules:
aoeu256

2

Ще один варіант:

$ cat << EOF > ~/.ipython/profile_default/startup/50-autoreload.ipy
%load_ext autoreload
%autoreload 2
EOF

Перевірено на ipython та ipython3 v5.1.0 на Ubuntu 14.04.


1

Моя стандартна практика перезавантаження - поєднувати обидва способи після першого відкриття IPython:

from IPython.lib.deepreload import reload
%load_ext autoreload
%autoreload 2

Завантаження модулів перед цим призведе до того, що вони не будуть перезавантажені навіть у посібнику reload(module_name). У мене все ще, дуже рідко, виникають незрозумілі проблеми з методами класу, які не перезавантажуються, які я ще не вивчав.


1

Зауважте, що вищезгадане autoreloadпрацює лише в IntelliJ, якщо ви вручну зберігаєте змінений файл (наприклад, використовуючи ctrl + s або cmd + s). Схоже, це не працює з автоматичним збереженням.


Я підтверджую, що це стосується і PyCharm.
tsando

0

На ноутбуках Юпітера про Анаконда:

%load_ext autoreload
%autoreload 2

видав повідомлення:

Розширення автозавантаження вже завантажено. Щоб перезавантажити його, використовуйте: %reload_ext autoreload

Схоже, це краще робити:

%reload_ext autoreload
%autoreload 2

Інформація про версію:

Версія сервера ноутбуків 5.0.0 і працює на: Python 3.6.2 | Anaconda, Inc. | (за замовчуванням, 20 вересня 2017, 13:35:58) [MSC v.1900 32 біт (Intel)]


0

Будь-які суб’єкти не будуть перезавантажені цим, я вважаю, що вам доведеться використовувати для цього поглиблення IPython.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.