在 python 中执行模块主体之前,有没有办法在模块内部修补 class?
Is there a way to monkey patch a class inside a module before the module body is executed in python?
我有文件 main.py
,其中包含以下代码:
class A:
def __init__(self, a):
self.a = a
def run(self):
return self.a+10
a = A(4)
print(a.run())
在文件 test.py
中,我尝试对 main.py
中的 class A
进行猴子补丁,如下所示:
import main
class A:
def __init__(self, a):
self.a = a
def run(self):
return self.a+5
main.A = A
不幸的是,当我从 python 解释器 运行 import test
时,模块仍然打印出 14
而不是我预期的输出 9
.
有没有办法在执行模块主体之前在模块内部修补 class?
这里的问题是,当您 import
编辑 main.py
文件时,它使用 class [=14= 的实际实现来执行代码 a = A(4)
].然后你的 test.py
的其余部分被执行并且你替换了 A
引用,但是为时已晚。
您可以通过添加测试来检查:
print(__name__) # __main__
print(main.__name__) # so70731368_main
print(A.__module__) # __main__
print(main.A.__module__) # __main__
print(main.a.__class__.__module__) # so70731368_main
在这里,__main__
有点令人困惑,但这就是 Python 调用您 运行 的第一个文件的方式(在您的情况下 test.py
)。 a
实例是在 so70731368_main
模块中声明的,它使用了同一模块中的 A
class,你只是在事后更改了 A
来自测试文件的定义 (__main__
).
您需要修补同一文件中定义的两个定义(A
和 a
)这一事实非常棘手。 unittest.mock.patch
的功能不足以修补 inside 导入(它修补 after 导入)。
您不能以简洁明了的方式阻止 a
被实例化为 main.A
(真实)class 并打印出来。你可以做的是修补它之后,供以后使用,这就是你所展示的。
直接回答您的问题:“修补”意味着用一个引用替换另一个引用,因此必须已经定义了引用。在您的示例中,它需要在 class 定义和 class 实例化之间进行修补(因为 print
不使用真正的 a
),这是不支持的。
这个问题没有简单的解决方案。如果您可以控制 main.py
文件的代码,请尝试更改它,使其在导入时不实例化 a
。
我有文件 main.py
,其中包含以下代码:
class A:
def __init__(self, a):
self.a = a
def run(self):
return self.a+10
a = A(4)
print(a.run())
在文件 test.py
中,我尝试对 main.py
中的 class A
进行猴子补丁,如下所示:
import main
class A:
def __init__(self, a):
self.a = a
def run(self):
return self.a+5
main.A = A
不幸的是,当我从 python 解释器 运行 import test
时,模块仍然打印出 14
而不是我预期的输出 9
.
有没有办法在执行模块主体之前在模块内部修补 class?
这里的问题是,当您 import
编辑 main.py
文件时,它使用 class [=14= 的实际实现来执行代码 a = A(4)
].然后你的 test.py
的其余部分被执行并且你替换了 A
引用,但是为时已晚。
您可以通过添加测试来检查:
print(__name__) # __main__
print(main.__name__) # so70731368_main
print(A.__module__) # __main__
print(main.A.__module__) # __main__
print(main.a.__class__.__module__) # so70731368_main
在这里,__main__
有点令人困惑,但这就是 Python 调用您 运行 的第一个文件的方式(在您的情况下 test.py
)。 a
实例是在 so70731368_main
模块中声明的,它使用了同一模块中的 A
class,你只是在事后更改了 A
来自测试文件的定义 (__main__
).
您需要修补同一文件中定义的两个定义(A
和 a
)这一事实非常棘手。 unittest.mock.patch
的功能不足以修补 inside 导入(它修补 after 导入)。
您不能以简洁明了的方式阻止 a
被实例化为 main.A
(真实)class 并打印出来。你可以做的是修补它之后,供以后使用,这就是你所展示的。
直接回答您的问题:“修补”意味着用一个引用替换另一个引用,因此必须已经定义了引用。在您的示例中,它需要在 class 定义和 class 实例化之间进行修补(因为 print
不使用真正的 a
),这是不支持的。
这个问题没有简单的解决方案。如果您可以控制 main.py
文件的代码,请尝试更改它,使其在导入时不实例化 a
。