В Python, когда я импортировал модуль X в сеанс интерпретатора с использованием import X
, и модуль изменился снаружи, я могу перезагрузить модуль с помощью reload(X)
. Затем изменения становятся доступны в моем сеансе интерпретатора.
Мне интересно, возможно ли это, когда я импортирую компонент Y из модуля X, используя from X import Y
.
Этот оператор reload Y
не работает, поскольку Y не является модулем, а только компонентом (в данном случае классом) внутри модуля.
Возможно ли вообще перезагрузить отдельные компоненты модуля, не выходя из сеанса интерпретатора (или импортировав весь модуль)?
РЕДАКТИРОВАТЬ:
Для пояснения вопрос касается импорта класса или функции Y из модуля X и перезагрузки при изменении, а не модуля Y из пакета X.
python
python-import
cschol
источник
источник
... possible ... import a component Y from module X
«противquestion is ... importing a class or function X from a module Y
». Я добавляю правку к этому эффекту.Ответы:
Если Y - модуль (а X - пакет),
reload(Y)
все будет в порядке - иначе вы поймете, почему в хороших руководствах по стилю Python (например, от моего работодателя) говорится, что никогда не следует импортировать ничего, кроме модуля (это одна из многих веских причин. - но люди до сих пор держать импортирования функции и классы напрямую, независимо от того , сколько я объясняю , что это не очень хорошая идея ;-).источник
import this
из интерактивной подсказки, чтобы увидеть Zen of Python); и все причины, по которым пространства имен являются отличной идеей (немедленные локальные визуальные подсказки того, что имя просматривается, простота имитации / внедрения в тестах, возможность перезагрузки, возможность гибкого изменения модуля путем переопределения некоторых записей, предсказуемость и управляемость поведение при сериализации и восстановлении ваших данных [[например, путем травления и распаковки]] и так далее, и так далее - комментарий SO вряд ли достаточно длинный, чтобы отдать должное этому богатому, длинному аргументу !!! -)importlib
пакет.importlib.reload(Y)
docs.python.org/3.4/library/… см. также stackoverflow.com/questions/961162/…Ответ
Судя по моим тестам, отмеченный ответ, предполагающий простой
reload(X)
, не работает.Из того, что я могу сказать, правильный ответ:
from importlib import reload # python 2.7 does not require this import X reload( X ) from X import Y
Контрольная работа
Мой тест был следующим (Python 2.6.5 + bpython 0.9.5.2)
X.py:
def Y(): print "Test 1"
bpython:
>>> from X import Y >>> print Y() Test 1 >>> # Edit X.py to say "Test 2" >>> print Y() Test 1 >>> reload( X ) # doesn't work because X not imported yet Traceback (most recent call last): File "<input>", line 1, in <module> NameError: name 'X' is not defined >>> import X >>> print Y() Test 1 >>> print X.Y() Test 1 >>> reload( X ) # No effect on previous "from" statements >>> print Y() Test 1 >>> print X.Y() # first one that indicates refresh Test 2 >>> from X import Y >>> print Y() Test 2 >>> # Finally get what we were after
источник
Foo
который__init__.py
выбирает подмодуль ... Я отправлю ответ в качестве контрпримера.from modulename import func import importlib, sys importlib.reload(sys.modules['modulename']) from modulename import func
источник
Во-первых, вам вообще не следует использовать перезагрузку, если вы можете этого избежать. Но предположим, что у вас есть причины (например, отладка внутри IDLE).
При перезагрузке библиотеки имена не вернутся в пространство имен модуля. Для этого достаточно переназначить переменные:
f = open('zoo.py', 'w') f.write("snakes = ['viper','anaconda']\n") f.close() from zoo import snakes print snakes f = open('zoo.py', 'w') f.write("snakes = ['black-adder','boa constrictor']\n") f.close() import zoo reload(zoo) snakes = zoo.snakes # the variable 'snakes' is now reloaded print snakes
Вы можете сделать это несколькими другими способами. Вы можете автоматизировать процесс, выполнив поиск в локальном пространстве имен и переназначив все, что было от рассматриваемого модуля, но я думаю, что мы достаточно злы.
источник
Если вы хотите это сделать:
from mymodule import myobject
Вместо этого сделайте это:
import mymodule myobject=mymodule.myobject
Теперь вы можете использовать myobject так же, как и планировали (без утомительных нечитаемых ссылок на mymodule повсюду).
Если вы работаете в интерактивном режиме и хотите перезагрузить myobject из mymodule, теперь вы можете использовать:
источник
предполагая, что вы использовали
from X import Y
, у вас есть два варианта:reload(sys.modules['X']) reload(sys.modules[__name__]) # or explicitly name your module
или
Y=reload(sys.modules['X']).Y
несколько соображений:
A. Если область импорта не распространяется на весь модуль (например, g: импорт в функции), вы должны использовать вторую версию.
B. если Y импортирован в X из другого модуля (Z) - вы должны перезагрузить Z, затем перезагрузить X, а затем перезагрузить модуль, даже перезагрузка всех ваших модулей (например, использование
[ reload(mod) for mod in sys.modules.values() if type(mod) == type(sys) ]
) может перезагрузить X перед перезагрузкой Z - и затем не обновлять значение Y.источник
reload()
модульX
,reload()
импорт модуляY
изX
.Обратите внимание, что перезагрузка не изменит уже созданные объекты, связанные в других пространствах имен (даже если вы будете следовать руководству по стилю от Alex).
источник
Если вы работаете в среде jupyter, и вы уже
from module import function
можете использовать функцию магии, сautoreload
помощью%load_ext autoreload %autoreload from module import function
Введение
autoreload
в IPython дается здесь .источник
Просто чтобы продолжить ответы AlexMartelli и Catskul , есть несколько действительно простых, но неприятных случаев, которые, кажется, сбивают с толку
reload
, по крайней мере, в Python 2.Предположим, у меня есть следующее дерево исходников:
со следующим содержанием:
init.py:
from bar import Bar, Quux
bar.py:
print "Loading bar" class Bar(object): @property def x(self): return 42 class Quux(Bar): object_count = 0 def __init__(self): self.count = self.object_count self.__class__.object_count += 1 @property def x(self): return super(Quux,self).x + 1 def __repr__(self): return 'Quux[%d, x=%d]' % (self.count, self.x)
Это прекрасно работает без использования
reload
:>>> from foo import Quux Loading bar >>> Quux() Quux[0, x=43] >>> Quux() Quux[1, x=43] >>> Quux() Quux[2, x=43]
Но попробуйте перезагрузить, и это либо не работает, либо портит вещи:
>>> import foo Loading bar >>> from foo import Quux >>> Quux() Quux[0, x=43] >>> Quux() Quux[1, x=43] >>> reload(foo) <module 'foo' from 'foo\__init__.pyc'> >>> Quux() Quux[2, x=43] >>> from foo import Quux >>> Quux() Quux[3, x=43] >>> reload(foo.bar) Loading bar <module 'foo.bar' from 'foo\bar.pyc'> >>> Quux() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "foo\bar.py", line 17, in __repr__ return 'Quux[%d, x=%d]' % (self.count, self.x) File "foo\bar.py", line 15, in x return super(Quux,self).x + 1 TypeError: super(type, obj): obj must be an instance or subtype of type >>> Quux().count 5 >>> Quux().count 6 >>> Quux = foo.bar.Quux >>> Quux() Quux[0, x=43] >>> foo.Quux() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "foo\bar.py", line 17, in __repr__ return 'Quux[%d, x=%d]' % (self.count, self.x) File "foo\bar.py", line 15, in x return super(Quux,self).x + 1 TypeError: super(type, obj): obj must be an instance or subtype of type >>> foo.Quux().count 8
Единственный способ обеспечить
bar
перезагрузку подмодуля - этоreload(foo.bar)
: единственный способ получить доступ к перезагруженномуQuux
классу - это достать его из перезагруженного подмодуля; но самfoo
модуль продолжал удерживать исходныйQuux
объект класса, предположительно потому, что он используетfrom bar import Bar, Quux
(а неimport bar
за нимQuux = bar.Quux
); более того,Quux
класс рассинхронизировался сам с собой, что просто странно.источник