【问题标题】:Workaround for bugs in Python packagesPython 包中的错误的解决方法
【发布时间】:2011-12-18 15:54:58
【问题描述】:

我最近遇到了以下问题:我正在用 Python 开发一个数值库(称为 spuq),其核心需要 scipy。现在 scipy 中的一个函数,称为btdtri,对于某些输入参数元组有一个错误。然而,根据 scipy 的开发人员的说法,这个错误现在已在 scipy 0.9 版中得到修复。所以在我的代码中我有这样的东西:

import scipy

def foo(a, b, c):
  if scipy.__version__>=(0, 9):
      return btdtri(a, b, c)
  else:
      return my_fixed_btdtri(a, b, c)

这可行,但是,我真的不喜欢在我的代码中乱扔第三方软件包的错误修复。我宁愿将它包含在一个模块中,实现解决方法,并让我的所有其他模块自动使用修补模块。

现在我的问题是:一般而言,处理此类案件的最佳做法是什么?例如。写我自己的spuq.contrib.scipy 并说在那里

from scipy import *
if __version__ < (0, 9):
  btdtri = my_fixed_btdtri

而不是到处导入scipy 导入spuq.contrib.scipy?我认为这很复杂,很容易忘记(而且可能是不合常规和丑陋的)。也许有一种方法可以自动“挂钩”到包加载并直接修改scipy 模块,以便其他每个包只看到修补过的包?我认为这个问题很常见,所以可能应该有一些“最佳实践”。

【问题讨论】:

    标签: python package


    【解决方案1】:

    您可以“猴子补丁”scipy 模块。在你的初始化代码的某个地方,做

    import scipy.special
    if scipy.version.version < "0.9.0":
        scipy.special.btdtri = my_btdtri
    

    由于模块只导入一次,所以只有一个模块scipy.special,所有其他模块只能看到猴子补丁版本。

    Monkey 修补程序通常被视为对测试有用,但对生产代码无效。不过,在这种情况下,我认为这很好,因为您并没有真正改变包的行为——您正在修复一个已确认的错误。

    【讨论】:

    • 那么你会在哪里做呢?在主包的__init__ 模块中?
    • 您需要确保在使用from scipy.version import btdtri调用或导入函数之前执行代码。 (无论如何,你不应该做后者。)这个地方在哪里取决于你的应用程序的结构。
    • 我不太喜欢这种方法,因为它更改了 scipy 模块,用于导入 scipy 和 OP 代码的任何代码。通过一些条件导入技巧,客户端代码使用的btdtri 可能因调用而异。
    • @larsmans:在某些情况下可能会发生这种情况。但我看不出始终使用错误版本比几乎总是使用固定版本更好。
    • @larsmans:spuq的客户端代码直接调用btdtri()的可能性很小。如果是这样,它很可能会获得固定版本。如果它进行了奇怪的导入并最终得到了错误的版本,它会一直崩溃——这里没有什么不可重现的事情发生。您不会建议人们不要修复他们自己的库中的错误,因为客户端代码中的错误将不再可重现,对吗? :)
    【解决方案2】:

    最好的选择是制作一个模块,比如fixes,根据 SciPy 版本导出固定版本或外部版本btdtri,如您的示例所示。它可以做得更简单:

    if scipy.version.version < (0,9,0):
        def btdtri(...):
            # whatever
    else:
        btdtri = scipy.btdtri
    

    与您的版本相比,这有一个优势,像 pyflakes 这样的代码检查工具不会阻塞 import *,而且您不需要从 fixes 模块获取所有 SciPy API,只需需要修复的部分(记住:显式优于隐式)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-01-11
      • 2011-01-19
      • 2014-03-22
      • 2012-01-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-04
      相关资源
      最近更新 更多