Numpy: 有时,supress_warnings会丢失其属性之一

创建于 2016-12-23  ·  60评论  ·  资料来源: numpy/numpy

尝试编译skimage时,有时会出现以下错误:

Traceback (most recent call last):
  File "/usr/lib/python2.7/dist-packages/nose/case.py", line 197, in runTest
    self.test(*self.arg)
  File "/build/skimage-0.12.3/debian/tmp/usr/lib/python2.7/dist-packages/skimage/transform/tests/test_integral.py", line 46, in test_vectorized_integrate
    assert_equal(expected, integrate(s, r0, c0, r1, c1))  # test deprecated
  File "/build/skimage-0.12.3/debian/tmp/usr/lib/python2.7/dist-packages/skimage/transform/integral.py", line 86, in integrate
    warn("The syntax 'integrate(ii, r0, c0, r1, c1)' is "
  File "/build/skimage-0.12.3/debian/tmp/usr/lib/python2.7/dist-packages/skimage/_shared/_warnings.py", line 16, in warn
    warnings.warn(message, stacklevel=stacklevel)
  File "/usr/lib/python2.7/dist-packages/numpy/testing/utils.py", line 2199, in _showwarning
    self._orig_show(message, category, filename, lineno,
AttributeError: 'suppress_warnings' object has no attribute '_orig_show'

我认为这是一个麻木的问题,但我不确定。

00 - Bug numpy.testing

所有60条评论

嗯,有点奇怪。 skimage测试中是否存在一些(奇怪的)线程? 这会严重破坏警告测试,因为警告处理在python中不是线程安全的。 我很难看到还会发生这种情况,但也许应该看一下测试运行的确切代码。

因为这里没有assert_warns左右,所以我想。 您应该只有一个suppress_warnings上下文可以运行(这是最外面的范围,由numpy的测试运行程序创建,假设skimage最终使用了它)。 现在让我感到困惑的是,只有在上下文已经退出的情况下,才有可能不定义_orig_show 。 那时warnings.showwarning应该已经重置为旧值。

当然,如果您有线程,则整个警告内容都会崩溃。 例如:

线程1:进入警告上下文->替换常规警告打印
线程2:输入警告上下文->替换线程1警告处理程序
线程1:退出警告上下文->重置为正常警告打印
thread2:存在警告上下文->重置为thread1的警告处理程序-> kaboom。

顺便说一句。 我看到您有一个“尝试在skimage中的__warning_registry__东西之后清理,抑制警告是试图解决类似问题(并添加一些其他东西)的上下文管理器,可能有趣,也可能不有趣。

当我尝试为Debian构建skimage时才遇到问题,我在这里一无所知。 但是,我打开了scikit-image / scikit-image#2412使其参与其中。

出于完整性考虑:有时,我什至在没有skimage参与的情况下获得了stacktrace:

ERROR: test suite for <module 'skimage.transform.tests' from '/build/skimage-0.12.3/debian/tmp/usr/lib/python3/dist-packages/skimage/transform/tests/__init__.py'>
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/nose/suite.py", line 229, in run
    self.tearDown()
  File "/usr/lib/python3/dist-packages/nose/suite.py", line 352, in tearDown
    self.teardownContext(ancestor)
  File "/usr/lib/python3/dist-packages/nose/suite.py", line 368, in teardownContext
    try_run(context, names)
  File "/usr/lib/python3/dist-packages/nose/util.py", line 453, in try_run
    inspect.getargspec(func)
  File "/usr/lib/python3.5/inspect.py", line 1040, in getargspec
    stacklevel=2)
  File "/usr/lib/python3/dist-packages/numpy/testing/utils.py", line 2199, in _showwarning
    self._orig_show(message, category, filename, lineno,
AttributeError: 'suppress_warnings' object has no attribute '_orig_show'

您正在使用什么版本的python,numpy等进行编译?

Numpy 1.12〜RC〜beta 1,Python 2.7和3.5
(对不起,我的错误:尚未检查RC)

嗯,我很困惑....我不明白为什么会有线程问题,但也不能真正参透这个错误发生的历史没有任何的竞争条件或不正确的嵌套catch_warning状的东西(包括suppress_warning )。

我也认为这是一种竞赛条件,因为它并不总是发生。 在完全相同的环境下运行两次构建会使问题在不同的地方(甚至根本没有)弹出。

@olebole

从我们的测试套件中复制:

#!/bin/sh
set -efu

pys="$(pyversions -rv 2>/dev/null)"
pkgbuild=${pkgbuild:-no}

srcdir=$PWD

for py in $pys; do
    echo "=== python$py ==="
    if [ "$pkgbuild" = "yes" ]; then
        export PYTHONPATH="$srcdir/debian/tmp/usr/lib/python$py/dist-packages"
        cd "$srcdir/build/"
    else
        cd "$ADTTMP"
    fi

    xvfb-run -a python$py /usr/bin/nosetests -s -v --exclude test_tools.py skimage 2>&1
done

xvfb-run在那里,因为测试需要在X11环境中运行。

嗯,有人知道鼻子开始测试模块时引擎盖下到底发生了什么吗? 鼻子让我感到困惑,我不明白为什么它最终还会弄乱警告……。或者毕竟这是抑制警告的一个错误,但是却看不到,嘿。

在我的鼻子测试手册页中,我有

       --processes=NUM
              Spread  test run among this many processes. Set a number equal to the number of processors or cores in your machine for best results. Pass a negative
              number to have the number of processes automatically set to the number of cores. Passing 0 means to disable parallel testing.  Default  is  0  unless
              NOSE_PROCESSES is set. [NOSE_PROCESSES]

似乎默认情况下没有并行测试。 至少,竞争条件不应该存在。

基于垃圾回收的东西,鼻子有没有机会运行这个teardownContext

不,我可能很傻。 抑制警告上下文会在删除属性之前重置warnings.showwarning ,因此即使gc插入也无法在没有其他事情的情况下真正创建任何东西。 只是不知道还有什么:)。

好吧,我发现skimage-0.9.3出现了33个错误,大部分来自PIL或索引编制,但没有抑制错误。 您如何处理所有其他错误?

@charris报告此问题的原因是0.12.3,而不是0.9.3。 :)

好吧,终于从上游撤回了它,现在有39个错误和大量弃用。 大多数警告似乎是由于测试认为它们在QT中而不是Wayland中运行而引起的,这可能是此处的配置问题。 我还需要运行测试

python -c'import skimage; skimage.test()'

因为nosetests根本不起作用。

弃用是正常的。 即使预计会弃用,我们仍然会检查旧的API。 关于错误,这是不正常的。 您介意在我们的(scikit图像)错误跟踪器中报告这些错误吗?

@sciunto文档可以使用说明进行本地测试。

好的,我在同一地方看到它。 测试是

def test_vectorized_integrate():
    r0 = np.array([12, 0, 0, 10, 0, 10, 30])
    c0 = np.array([10, 0, 10, 0, 0, 10, 31])
    r1 = np.array([23, 19, 19, 19, 0, 10, 49])
    c1 = np.array([19, 19, 19, 19, 0, 10, 49])

    expected = np.array([x[12:24, 10:20].sum(),
                         x[:20, :20].sum(),
                         x[:20, 10:20].sum(),
                         x[10:20, :20].sum(),
                         x[0,0],
                         x[10, 10],
                         x[30:, 31:].sum()])
    start_pts = [(r0[i], c0[i]) for i in range(len(r0))]
    end_pts = [(r1[i], c1[i]) for i in range(len(r0))]
    assert_equal(expected, integrate(s, r0, c0, r1, c1))  # test deprecated
    assert_equal(expected, integrate(s, start_pts, end_pts))

# test deprecated注释向我表明,也许测试需要一些修复,但是suppress_warnings仍然应该更自然地失败。

一点点信息,做

$ python skimage/transform/tests/test_integral.py

哪个使用NumPy run_module_suite似乎没有失败,但是会发出警告

======================================================================
ERROR: skimage.transform.tests.test_integral.test_vectorized_integrate
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib/python2.7/site-packages/nose/case.py", line 197, in runTest
    self.test(*self.arg)
  File "/home/charris/Workspace/scikit-image/skimage/transform/tests/test_integral.py", line 46, in test_vectorized_integrate
    assert_equal(expected, integrate(s, r0, c0, r1, c1))  # test deprecated
  File "/home/charris/Workspace/scikit-image/skimage/transform/integral.py", line 86, in integrate
    warn("The syntax 'integrate(ii, r0, c0, r1, c1)' is "
  File "/home/charris/Workspace/scikit-image/skimage/_shared/_warnings.py", line 16, in warn
    warnings.warn(message, stacklevel=stacklevel)
UserWarning: The syntax 'integrate(ii, r0, c0, r1, c1)' is deprecated, and will be phased out in release 0.14. The new syntax is 'integrate(ii, (r0, c0), (r1, c1))'.

请注意,scikit-image在skimage/_shared/_warnings.py具有自己的警告警告上下文管理器。 这可能与suppress_warnings冲突。

出于好奇,我想知道显式指定DeprecationWarning而不使用默认的UserWarning

所以我看不到错误

$ nosetests-2.7 skimage/transform/tests/test_integral.py |& grep orig_show

鉴于

$ nosetests-2.7 skimage/transform/tests/ |& grep orig_show

大约有25%的时间显示。 这表明错误的根源在其他地方,而失败的测试只是将其暴露出来。

特别是skimage/transform/tests/test_geometric.py包含警告上下文管理器expected_warnings ,这使我感到怀疑。

好的,现在我怀疑test_parallel装饰器, https://github.com/scikit-image/scikit-image/blob/master/skimage/_shared/testing.py 。 默认为两个线程。

如果我删除了导入test_parallel的三个文件,则不再存在问题。

编辑:现在我根本无法重现该问题。 嗯...也许还取决于机器上正在运行什么。

嗯, test_parallel可能就是我想的,尽管通过代码查看,没有一个函数显然使用警告上下文,尽管我猜并不是不可能。

test_hough_transform.py某些内容似乎是发起者。 删除该文件后,没有错误。

编辑:也许是因为在test_integral.py模块之前?

问题似乎是在test_hough_transform.py

@test_parallel()
def test_hough_circle():
    # Prepare picture
    img = np.zeros((120, 100), dtype=int)
    radius = 20
    x_0, y_0 = (99, 50)
    y, x = circle_perimeter(y_0, x_0, radius)
    img[x, y] = 1

    out1 = tf.hough_circle(img, radius)
    out2 = tf.hough_circle(img, [radius])
    assert_equal(out1, out2)
    out = tf.hough_circle(img, np.array([radius], dtype=np.intp))
    assert_equal(out, out1)
    x, y = np.where(out[0] == out[0].max())
    assert_equal(x[0], x_0)
    assert_equal(y[0], y_0)

特别是两条线中的任何一条

    assert_equal(out1, out2)

# or

    assert_equal(out, out1)

将启用该错误。

同样,删除@parallel装饰器也可以修复该错误。 因此,结果是线程与向量调用的assert_equal结合使用会导致问题。

有意义,断言等于函数使用它来过滤".*NAT =="警告,我们可能会尝试将其从该函数中删除,因为它不是很明显assert_equal会进行警告抑制(因此不能完全消除警告)支持线程)。

很好地追踪Chuck!

尝试删除它是一件好事。

我想知道是否还有其他不是线程安全的numpy函数?

不确定,我认为我们仅在测试服中使用警告内容。 np.errstate可能是线程安全的吗?

非常感谢您对@charris@seberg进行的出色调查

嗯,我觉得有点烦。 删除抑制的位置可能会改变下游的行为,这可能很好(甚至更干净),但不确定对错误修正版本有什么好处。 也可以将互斥锁锁定在比较类型测试上,这在原则上可能并不总是很好,但我真的无法考虑它可能如何中断。

我认为仅修复assert_equal就足够了,将来无论如何都要对NaT比较进行修复。 请注意,NaT可以转换为int64,其值min_int64。

哦,是的,实际上,我们实际上可以明确地支持NaT,目前有点烦人(因为没有专门检查NaT的功能),但并不难。 关于其他数组比较,还有其他事情,但是我想它并没有太多使用(并且不确定什么)。

在断言中添加NaT逻辑对于master来说似乎效果很好,尽管我不确定它是否可以用于反向移植。 我认为虽然suppress_warnings可能是新的,但竞赛条件本身在上一发行版中已经存在。

我们仍然需要isnat函数或在isnan支持datetime/timedelta isnan

是的,同意isnat函数。 累加器还有两种类型: timedelta64datetime64 。 请注意,NaT值也不显示在任何地方,我们也可以使用np.nat 。 实际定义在ndarraytypes.h

@ charris ,Chuck,您np.isnat或宁可在isnan允许datetime和timedelta?

嗯,将其全部放入isnan是一个有趣的想法,但我怀疑这可能会在此时或之后引起麻烦? @njsmith @juliantaylor有什么想法吗?

@shoyer也可能有意见。

我刚刚实现了isnat ,但是我不确定有关该发行版的所有时间安排。 如果我们必须尝试以最小版本修复此问题,则更好的选择可能是将python isnat版本插入测试服,尽管在任何情况下修复它都可能有些棘手(至少其他人会比以前收到更多警告,尽管可能很少1.使用我们的测试服和2.仔细测试警告)。

我认为失败不是很严重,但是修复它会很好。 我可以使用(私有的)python版本的isat来获得1.12。

suppress_warnings文档字符串还应该提到它不是线程安全的。

它是:)

非常感谢大家在假期中跳过这个问题并进行了彻底的调试

我有什么办法可以实现/测试解决方案? debian渴望为此解决问题:)

@sandrotosi ,不幸的是,这可能有点棘手,最简单的解决方法可能是根本不使用skimage中的并行测试内容,但这有点违背了目的。 我们可以简单地在我的isat资料中做类似的事情(使用isat的专用python版本)。 但是,我不太确定它可能不会在其他地方创建测试回归:/。

为这两种情况添加互斥锁实际上可能是一个合理的破解程序,它应该可以消除麻烦,并且似乎不太可能变坏(因为您不会从assert_equal内部调用assert_equal或类似名称)。 我实际上不会在numpy master中使用它,但是作为1.12的最小错误修正,它可能是一个真实的选择。 并且它不会干扰skimage测试本身。

@olebole是否可以在skimage中禁用并行测试?

@seberg是的,我认为目标可能是对1.12进行最小修复,并最终以更完整/更全面的方式在master中解决它-至少可以使下一个debian版本在没有此问题的情况下

@sandrotosi我在gh-8427中尝试了锁定方法。 我不是那个想法是否疯狂,但是如果有人想尝试...。

有什么方法可以简单地将suppress_warnings修改

(我有一些想法,但我仍在思考它到底如何工作。)

当然,我们不能删除该属性,但是稍后可能会在测试中创建错误……尽管我猜大多数测试套件对测试警告的理解都不如numpy,所以……。

我已经将1.12.0rc2(包含https://github.com/numpy/numpy/pull/8427)上传到debian,并重建了3次skimage(debian软件包的旧版本,未完全禁用测试套件)并且它成功构建的所有时间。

非常感谢大家在假期中为此工作!

现在,最终的1.12.0版本有什么计划? :)

我计划于1月15日发布最终版本。

我可以确认它可以与rc2一起使用。 非常感谢你的努力!

我将其保持打开状态,直到将其固定在母版中为止。

嗯,不是固定在主人。 @seberg #8421将关闭它是否正确?

由#8421修复。

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

dmvianna picture dmvianna  ·  4评论

inducer picture inducer  ·  3评论

Kreol64 picture Kreol64  ·  3评论

ghost picture ghost  ·  4评论

dcsaba89 picture dcsaba89  ·  3评论