Повторно імпортуйте модуль у python під час інтерактивності


382

Я знаю, що це можна зробити, але я ніколи не пам'ятаю, як.

Як можна повторно імпортувати модуль у python? Сценарій такий: я імпортую модуль в інтерактивному режимі і переглядаю його, але потім я стикаюся з помилкою. Я виправляю помилку у файлі .py, а потім хочу повторно імпортувати фіксований модуль, не виходячи з python. Як я можу це зробити?



Відповіді:


368

Це має працювати:

reload(my.module)

З док. Python

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

Якщо ви працюєте з Python 3.4 і вище, зробіть import importlib, тоді зробіть importlib.reload(nameOfModule).

Не забувайте про застереження щодо використання цього методу:

  • Коли модуль перезавантажується, його словник (містить глобальні змінні модуля) зберігається. Перевизначення імен замінить старі визначення, тому це, як правило, не є проблемою, але якщо нова версія модуля не визначає ім'я, яке було визначене старою версією, старе визначення не видаляється.

  • Якщо модуль імпортує об’єкти з іншого модуля за допомогою from ... import ..., виклик reload()іншого модуля не переосмислює об'єкти, імпортовані з нього - один із способів цього - повторне виконання fromоператора, інший - використання importта встановлення імен ( module.*name*).

  • Якщо модуль інстанціює екземпляри класу, перезавантаження модуля, який визначає клас, не впливає на визначення методів екземплярів - вони продовжують використовувати старе визначення класу. Те саме стосується похідних класів.


26
якщо я завантажую свої модулі за допомогою from filename import *. Як перезавантажити?
Пітер Чжу

@PeterZhu для випадку "від mod import fcn" об'єкт модуля не додається до простору імен. Тому вам потрібно явно імпортувати модуль, щоб потім можна було його перезавантажити. import foo; from foo import bar; reload(foo)
Тед

Я спробував перезавантажити, як і магію автоматичного завантаження, і я бачу зміну коду, відображену в стеці повідомлення про помилку, але сама помилка все-таки видається поза застарілим кодом (наприклад, рядок помилки точно такий же рядок, як і раніше, який я змінив до коментаря, і коментар явно не може викликати помилки). Мій модуль завантажений як розширення Юпітера, може хтось знає, чи потрібна інша робота? Дякую!
yifanwu

1
Якщо ви імпортували свою функцію наступним чином "імпорт ім'я як ім'я", вам потрібно зробити наступне: "import importlib importlib.reload (name)"
Noe

Цей метод може не замінити посилання інших модулів на перезавантажений модуль. Див. Stackoverflow.com/a/61617169/2642356 для вирішення цього питання.
EZLearner

287

У python 3 reloadвже не вбудована функція.

Якщо ви використовуєте Python 3.4+ , ви повинні використовувати reloadз importlibбібліотеки замість:

import importlib
importlib.reload(some_module)

Якщо ви використовуєте python 3.2 або 3.3, слід:

import imp  
imp.reload(module)  

замість цього. Див. Http://docs.python.org/3.0/library/imp.html#imp.reload

Якщо ви використовуєте ipython, обов'язково подумайте про використання autoreloadрозширення:

%load_ext autoreload
%autoreload 2

Хоча багато Python-коду написано на Python 2, з кожним днем ​​Python 3 стає більш життєздатним варіантом. Дякую за пораду!
Аарон Джонсон

40
imp.reloadзастаріло з Python 3.4, замість цього використовуйте importlib.reloadфункцію .
jfs

1
@Andrew дякую! Я використовував% autoreload, це чудово, мої вже створені об'єкти автоматично отримали виправлену реалізацію методів класу, не відтворюючи їх
jeanmi

4
Я трохи запізнююся, але я думаю, що це не працює, якщо те, що вам потрібно перезавантажити, це функція або клас з модуля: якщо мій імпортний статтю from mymodule import myfunc, то importlib.reload(myfunc), тоді importlib.reload(mymodule.myfunc), importlib.reload(mymodule)всі дають NameError.
Пуф

@Puff дивіться мою відповідь нижче про те, як повторно імпортувати функцію
jss367

46

Власне, в Python 3 модуль imp позначений як ВІДКРИТИЙ. Ну, принаймні, це справедливо для 3,4.

Замість цього слід використовувати reloadфункцію з importlibмодуля:

https://docs.python.org/3/library/importlib.html#importlib.reload

Але майте на увазі, що ця бібліотека мала деякі зміни в API з останніми двома незначними версіями.


6

Якщо ви хочете імпортувати певну функцію або клас з модуля, ви можете зробити це:

import importlib
import sys
importlib.reload(sys.modules['my_module'])
from my_module import my_function

0

Хоча надані відповіді працюють для певного модуля, вони не перезавантажать підмодулі, як зазначено в цій відповіді :

Якщо модуль імпортує об’єкти з іншого модуля за допомогою from ... import ..., виклик reload()іншого модуля не переосмислює об'єкти, імпортовані з нього - один із способів цього полягає у повторному виконанні оператора from, інший - використанні importта кваліфікованих імен ( module.*name*) замість цього.

Однак якщо використовувати __all__змінну для визначення загальнодоступного API, можна автоматично перезавантажити всі загальнодоступні модулі:

# Python >= 3.5
import importlib
import types


def walk_reload(module: types.ModuleType) -> None:
    if hasattr(module, "__all__"):
        for submodule_name in module.__all__:
            walk_reload(getattr(module, submodule_name))
    importlib.reload(module)


walk_reload(my_module)

Застереження, зазначені в попередній відповіді, все ще дійсні. Зокрема, на зміну підмодулю, який не є частиною загальнодоступного API, як описано __all__змінною, перезавантаження за допомогою цієї функції не вплине. Аналогічно, видалення елемента з підмодуля не буде відображено перезавантаженням.

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