Как перезагрузить класс в оболочке Python? - PullRequest
55 голосов
/ 04 августа 2011

Если я импортирую модуль, определяющий класс с тем же именем, принадлежащим пакету, он импортируется как класс, а не как модуль из-за __init__.py родительского пакета.Смотрите различные результаты импорта в разных каталогах для подробностей.В оболочке Python или ipython, если я делаю

from MyPak import MyMod

, MyModule всегда импортируется как Class, поэтому я не могу перезагрузить его (reload () работает только для модулей).Повторный запуск

from MyPak import MyMod

, похоже, не обновляет определение класса.Кто-нибудь может предложить способ обновления класса в оболочке Python?

пс.без перезапуска интерпретатора Python.

pps .На всякий случай, если у вас есть код под рукой и вы хотите его протестировать: я на самом деле говорю о BioPython и работаю над Bio.PDB.PDBParser.У меня есть оболочка ipython (v0.10) и редактировать PDBParser.py.Просто не было возможности перезагрузить его в ipython.

, вот что я сделал:

# start ipython v0.10
import Bio
from Bio.PDB import PDBParser
p = PDBParser()
s = p.get_structure()
# then I make changes,e.g. simply print some text, in PDBParser.py
del Bio
del PDBParser
del s
import Bio  # or reload(Bio) without deleting all the objects
from Bio.PDB import PDBParser
p = PDBParser()
s = p.get_structure() # expected output after change not seen :(

Я не мог видеть напечатанный текст.Изменения не были применены как-то.

Ответы [ 6 ]

61 голосов
/ 04 августа 2011

Только на Python 3, импортируйте функцию reload:

>>> from importlib import reload

На Python 2.x и 3.x вы можете просто вызвать reloadв модуле:

>>> import MyPak
>>> reload(MyPak)
>>> from MyPak import MyMod

Однако экземпляры старого класса обновляться не будут (просто нет кода, описывающего механизм обновления).

36 голосов
/ 19 августа 2011

Я наконец нашел ответ:

import MyPak
from MyPak import MyMod

после редактирования файла MyPak/MyMod.py, чтобы перезагрузить класс MyMod в файле MyMod.py, необходимо

import sys
del sys.modules['MyPak.MyMod'] 
reload(MyPak)
from MyPak import MyMod

Предостережения :

  1. Выполнение del MyPak или del MyMod или del MyPak.MyMod не решает проблему, поскольку просто удаляет привязку имени. Python только ищет sys.modules, чтобы увидеть, были ли модули уже импортированы. Проверьте обсуждение в посте имя модуля в sys.modules и globals () .

  2. При перезагрузке MyPak python пытается выполнить строку from MyMod import MyMod в MyPak/__init__.py. Тем не менее, он находит MyPak.MyMod в sys.modules, таким образом, он будет НЕ перезагрузите MyMod, хотя MyPak/MyMod.py было обновлено. И вы обнаружите, что новый MyPak/MyMod.pyc не генерируется.

11 голосов
/ 26 декабря 2016

Есть три способа решить эту проблему:

1. Используйте import MyPak.MyMod вместо from MyPak import MyMod

Тогда вы можете написать:

from importlib import reload  # If on Python 3
import MyPak.MyMod
reload(MyPak.MyMod)

и это работает.

2. Использовать IPython.lib.deepreload

from MyPak import MyMod
from IPython.lib.deepreload import reload
reload(MyPak)  # This should also reload all submodules

3. Используйте автозагрузка магия

%load_ext autoreload
%autoreload 2
import MyPak.MyMod  # All changes to MyPak.MyMod will be loaded automatically
5 голосов
/ 25 ноября 2016

У меня есть один файл myfile.py, который содержит один класс MyClass

Для импорта просто выполните:

from myfile import MyClass
mc = MyClass()

Для перезагрузки:

import sys
del sys.modules['myfile']
from myfile import MyClass
modifiedmc = MyClass()

Это оченьполезно при сборке модулей.их можно поместить в функцию и просто вызвать функцию

def myreload():
   import sys
   del sys.modules['myfile']
   from myfile import MyClass
   modifiedmc = MyClass()
   global mc
   mc = modifiedmc
5 голосов
/ 07 ноября 2016

Вы можете использовать магическую функцию:

%load_ext autoreload
%autoreload 2
from MyPak import MyMod
0 голосов
/ 21 декабря 2016

Это работает для меня, используя python 3.5.2:

import importlib
importlib.reload(class)
from class import module
...