【发布时间】:2020-05-28 10:48:17
【问题描述】:
考虑三个模块a.py、b.py 和main.py。它们都可以位于任意位置,但为了示例,它们都将位于同一目录中。
模块a 通过使用importlib.util.spec_from_file_location 指定其路径来加载b,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'
如何从main.py 修补b.eggs,以便a.py 看到修补后的值?
从文件位置加载b 并在加载a 之前修补b.eggs 不起作用:
# 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 环境变量,所以我这样做。)
【问题讨论】:
标签: python import python-import monkeypatching