LINUX.ORG.RU

Возможно ли программно перезагрузить все from X import Y в Python?

 


0

1

Здравствуйте!

Имеется следующий код:

import foo
from foo import bar

bar()  # выполняется функция версии 1

# вносим изменения в foo.py

reload(foo)

bar()  # выполняется по-прежнему функция версии 1

Вопрос: если предположить, что неизвестно, что именно импортировалось из foo при помощи конструкции «from foo import X», или же по какой-то причине не хочется следить за этим - можно ли программно обновить все импортированные так функции и классы?

четвертый уже на подходе, а ты все со вторым ковыряешься, нехорошо. Потом заново все придется переучивать:)

onceagain2017
()

Да, конечно. Например

import foo
from foo import bar

import sys
del sys,modules['foo']

import foo
foo.bar()  # ver 2
bar()  # ver 1, естественно!
from foo import bar
bar()  # ver 2
t184256 ★★★★★
()
Ответ на: комментарий от t184256

Строчку «from foo import bar» явно использовать второй раз нельзя. Есть информация о том, что поменялся foo, но нет явной информации о том, что было из него импортировано (если такая информация нужна, то она должна получаться как-то программно).

Задачу можно переформулировать так:

import foo
from foo import bar

bar()  # выполняется функция версии 1

# вносим изменения в foo.py

reload_module_and_all_related_imports('foo')

bar()  # тут теперь должна выполнятся версия 2

при этом:

def reload_module_and_all_related_imports(module_name):
    # внутри этой функции есть информация только об имени модуля,
    # в который были внесены изменения, но нет информации о том,
    # что из него было импортировано (bar или что-то иное)

Фактический аналог: autoreload из jupyter https://ipython.org/ipython-doc/3/config/extensions/autoreload.html

Оттуда:

Functions and classes imported via ‘from xxx import foo’ are upgraded to new versions when ‘xxx’ is reloaded

omegatype ★★★
() автор топика
Последнее исправление: omegatype (всего исправлений: 1)
Ответ на: комментарий от omegatype

как вариант, и если в импортируемом модуле определен __all__ - можно пройтись по dir(sys.modules['__main__']) (ну или где тебе там перегрузить надо) и перегрузить все нужные. тащемто можно и без __all__ обойтись и просто проверять все глобальные у импортируемого модуля. проблема возникнет если bar это какаянибуть мутабельная переменная, тогда хрен ты ее распознаешь... но с функциями\классами все просто. ну а если имя bar всегда соответствует foo.bar то все вообще просто

genryRar ★★
()
Ответ на: комментарий от omegatype

Ну так это, во-первых, архитектуру тебе надо переделать, видно же, что чем попало страдаешь. Что следующим потребуешь, чтобы обновились функции в словарях? в замыканиях? в старых pickle'ах? Порочный это путь, нерешаемый.

Во-вторых, когда нужен аналог готового кода, обычно принято использовать вместо него его же самого.

t184256 ★★★★★
()
import sys, types
def reload_all():
    for k, v in globals().items():
        if type(v) == types.FunctionType and v.__module__ != "__main__":
            reload(sys.modules[v.__module__])
            globals()[k] = getattr(sys.modules[v.__module__], v.func_name)

или так

import sys, types, importlib
def reload_all():
    for k, v in globals().items():
        if type(v) == types.FunctionType and v.__module__ != "__main__":
            globals()[k] = getattr(importlib.import_module(v.__module__), v.func_name)

Вроде работает, но это только для функций импортированных таким образом(и глобально). Для классов и самих модулей допилишь сам, если надо.

pawnhearts ★★★★★
()
Последнее исправление: pawnhearts (всего исправлений: 2)

Да Common Lisp возьми уже :-) Там этот функционал из коробки :-)

anonymous
()
Ответ на: комментарий от t184256

что чем попало страдаешь
Порочный это путь, нерешаемый.

Просто интересно, вот тут тоже страдают чем попало и проч. из твоего списка? :-)

omegatype ★★★
() автор топика
Ответ на: комментарий от omegatype

Да, и сами признают это в Caveats.

Будь она решаемой, твой autoreload был бы в стандартной библиотеке. А язык назывался бы Erlang =)

t184256 ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.