【问题标题】:Python monkey patch a module that gets executed by another modulePython Monkey 修补由另一个模块执行的模块
【发布时间】:2014-03-22 08:20:15
【问题描述】:

我的问题与question类似

除了在thirdpartymodule_b中执行dosomething()不是我的模块,所以我需要猴子补丁thirdpartymodule_a并在thirdpartymodule_b中执行时生效

【问题讨论】:

  • 如果thirdpartymodule_b 已经在导入thirdpartymodule_a,我希望有人能告诉我这怎么可能。我从来没有这样做过。
  • 你想给thirdpartymodule_a打猴子补丁,这样只有thirdpartymodule_b使用补丁版本,而其他模块仍然使用旧版本?
  • @warwaruk 是正确的,原因是我想在 django 的第三方应用程序中修补一个表单,供其视图使用。
  • 我不太明白。如果您“在 django 中的第三方应用程序中修补一个表单,由它的视图使用”,您是否不希望其他模块也应该使用修补后的版本?
  • @warwaruk 是的,我希望同一个模块也应该使用补丁版本,我想你的答案猜到了,也许 urls.py 导入了在我的补丁之前导入表单的类视图。

标签: python


【解决方案1】:

我看不出你提到的问题和你的情况有什么不同。在这两种情况下,一个模块从另一个模块导入一个名称,而您想要修补该名称引用的对象。

在那个问题中,模块是作者编写的,在你的问题中,它是第三方模块。

我认为你的问题在于第三方已经导入了对象名称,所以如果你尝试替换它所在模块中的对象,第三方模块仍然会使用旧的,因为它仍然引用旧对象。

module_1.py

class AForm(Form):
    ...

module_2.py

from module_1 import AForm

如果你导入module_2 然后猴子补丁module_1 用另一个对象替换AForm

class AFormPatched(Form):
    ...

import module_1
module_1.AForm = AFormPatched

您的更改不会影响module_2,因为module_2.AForm 仍指向原始对象。

解决这个问题:

选项 1。 module_2 应如下所示:

import module_1
module_1.AForm  # using AForm in this form

选项 2。 也打补丁module_2.AForm

class AFormPatched(Form):
    ...

import module_1
module_1.AForm = AFormPatched
import module_2
module_2.AForm = AFormPatched

或者不要修补 module_1 你只希望 module_2 使用修补版本。

选项 3。 对象的补丁属性。如果您不想或不能对所有使用对象名称的地方进行修补,有时如果您不替换对象,但仅修补其某些属性,则它会起作用。这取决于您尝试修补的对象和行为:

import third_party_module
third_party_module.AForm.__init__ = ...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-05-24
    • 2013-11-01
    • 1970-01-01
    • 2014-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-18
    相关资源
    最近更新 更多