Рассмотрим три модуля a.py
, b.py
и main.py
. Каждый из них может находиться в произвольном месте, но для примера все они будут в одном каталоге.
Модуль a
загружает b
, указав его путь с помощью importlib.util.spec_from_file_location
и main
делает то же самое с a
.
# b.py
eggs = 42
# a.py
import importlib.util
import os
B_PATH = os.path.join(os.path.dirname(__file__), 'b.py') # could be an arbitrary path
spec = importlib.util.spec_from_file_location('b', B_PATH)
b = importlib.util.module_from_spec(spec)
spec.loader.exec_module(b)
spam = "ham"
print(f"{__name__} says {b.eggs=}")
# main.py
import importlib.util
import os
A_PATH = os.path.join(os.path.dirname(__file__), 'a.py') # could be an arbitrary path
spec = importlib.util.spec_from_file_location('a', A_PATH)
a = importlib.util.module_from_spec(spec)
spec.loader.exec_module(a)
print(f"{__name__} says {a.spam=}")
Когда мы запускаем main.py
:
$ python main.py
a says b.eggs=42
__main__ says a.spam='ham'
Как я могу исправить b.eggs
из main.py
, чтобы a.py
видел исправленное значение? Загрузка b
из местоположения файла и исправление b.eggs
перед загрузкой a
не работает:
# main.py v2
import importlib.util
import os
B_PATH = os.path.join(os.path.dirname(__file__), 'b.py')
spec = importlib.util.spec_from_file_location('b', B_PATH)
b = importlib.util.module_from_spec(spec)
spec.loader.exec_module(b)
b.eggs = "patched"
A_PATH = os.path.join(os.path.dirname(__file__), 'a.py')
spec = importlib.util.spec_from_file_location('a', A_PATH)
a = importlib.util.module_from_spec(spec)
spec.loader.exec_module(a)
print(f"{__name__} says {a.spam=}")
print(f"{__name__} says {b.eggs=}")
$ python main.py
a says b.eggs=42
__main__ says a.spam='ham'
__main__ says b.eggs='patched'
Как я могу сделать это, не исправляя фактический исходный код b
?
(Обратите внимание, что в этом примере, поскольку все модули находятся в одном каталоге, импорт из пути к файлу глуп, так как это может быть выполнено с помощью оператора import
, но это просто чтобы сделать минимальный рабочий пример. В моем реальном случае мои модули находятся в разных каталогах, и я не могу изменить переменную среды PYTHONPATH
, поэтому я делаю это так.)