【问题标题】:How to monkey-patch an internal private function in a python package?如何对python包中的内部私有函数进行猴子补丁?
【发布时间】:2014-01-24 09:12:52
【问题描述】:

使用pygal 包时,我必须更改pygal.util 模块中的实用功能。该函数被其他模块中的其他函数调用。我如何猴子修补这个功能?现在,我已经编辑了 dist_packages 中的代码,但必须有一种方法可以动态分配给这个函数?

函数是pygal.util.is_major。我试图通过以下方式做到这一点: pygal.util.is_major = lambda x: False 但它不起作用。我认为这是因为包中的其他模块正在将此函数导入到它们的本地命名空间中。所以我改变它没有任何效果,因为旧版本的函数已经被其他模块导入到它们的本地命名空间中。

【问题讨论】:

  • 当您尝试直接分配给函数时会发生什么?即pygal.util.whatever = new_func
  • 是你在模块级别、类方法、实例方法上猴子补丁的函数吗?
  • @Narcolei 这不是万无一失的,因为在应用猴子补丁之前创建的其他命名空间中保存的任何引用都不会更新到补丁方法,但直接分配通常涵盖大多数情况,特别是如果您确保在程序执行中尽早进行修补。
  • @SilasRay 当然,这就是我发表评论而不是答案的原因。
  • 可以尝试获取函数对象并使用gc.get_referrers() 循环遍历对该函数的每个引用,然后修补每个对象引用以指向您的覆盖方法。 (以及进行上述简单的分配修补以处理创建的任何未来引用。)

标签: python monkeypatching


【解决方案1】:

分配给 is_major 不起作用的原因是因为另外两个 pygal 模块在您分配给它之前将 is_major 导入到它们的本地命名空间中。

pygal.graph.radar module:

from pygal.util import deg, cached_property, compute_scale, is_major

还有pygal.graph.graph module

from pygal.util import (
    is_major, truncate, reverse_text_len, get_texts_box, cut, rad, decorate)

如果您可以在导入其中任何一个模块之前对 is_major 函数进行猴子路径,它应该可以工作。如果你不能,你可以在猴子补丁后reload 图形模块。

类似这样的:

import pygal.util
import pygal.graph
import pygal.graph.radar

pygal.util.is_major = my_function
reload(pygal.graph)
reload(pygal.graph.radar)

【讨论】:

    猜你喜欢
    • 2012-12-12
    • 2016-08-25
    • 2013-04-13
    • 1970-01-01
    • 2013-12-28
    • 2012-12-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多