如何在Python中捕获RecursionError?

时间:2017-12-19 18:28:08

标签: python

我正在测试一个函数来在Python中查找数学函数的根,如果间隔中没有根,则会引发RecursionError。但是,当我尝试使用try-except块处理异常时,它不再被提升。我错过了什么?

import math
sgn = lambda x: math.copysign(1, x)

def bisect(f, a, b, eps=1e-6):
    """
    Find an approximate root of f in the interval [a, b].

    Parameters
    ----------
    f : function
        A mathematical function, defined and with root on [a, b]
    a, b : numbers
        Endpoints of the interval. a < b.
    eps : number, optional, default 1e-6
        Tolerance of error.

    Returns
    -------
    x : number
        Approximate root of f on [a, b]
    """
    if a > b:
        raise ValueError("`b` needs to be greater than `a` for the interval [a, b] to exist.")
    x = (a + b) / 2
    if abs(f(x)) < eps:
        return x
    try:
        if sgn(f(a)) != sgn(f(x)):
            return bisect(f, a, x, eps)
        else:
            return bisect(f, x, b, eps)
    except RecursionError as e:
        raise RecursionError(f"There seems to be no root of f on the interval [{a}, {b}]")

def test_bisect():
    """Verify `bisect` using `f` = cos(pi * x), `a` = 0 `b` = 0.82 and `eps` = 1e-12."""
    from math import cos, pi
    f = lambda x: cos(pi * x)
    a = 0
    b = 0.4
    eps = 1e-12
    expected = 0.5
    computed = bisect(f, a, b, eps)
    error = abs(expected - computed)
    tolerance = 1e-12
    success = error < tolerance
    msg = f"""
    Error testing `piecewise`.
    Expected:  {expected}
    Computed:  {computed}
    Error:     {error:13.6e}
    Tolerance: {tolerance:13.6e}"""
    assert success, msg

test_bisect()

2 个答案:

答案 0 :(得分:0)

我认为你的try/except位置错误了。我把它移到了test_bisect()函数里面。

import math

sgn = lambda x: math.copysign(1, x)

def bisect(f, a, b, eps=1e-6):
    """
    Find an approximate root of f in the interval [a, b].

    Parameters
    ----------
    f : function
        A mathematical function, defined and with root on [a, b]
    a, b : numbers
        Endpoints of the interval. a < b.
    eps : number, optional, default 1e-6
        Tolerance of error.

    Returns
    -------
    x : number
        Approximate root of f on [a, b]
    """
    if a > b:
        raise ValueError("`b` needs to be greater than `a` for the interval [a, b] to exist.")
    x = (a + b) / 2
    if abs(f(x)) < eps:
        return x
    if sgn(f(a)) != sgn(f(x)):
        return bisect(f, a, x, eps)
    else:
        return bisect(f, x, b, eps)

def test_bisect():
    """Verify `bisect` using `f` = cos(pi * x), `a` = 0 `b` = 0.82 and `eps` = 1e-12."""
    from math import sin, pi, cos
    f = lambda x: cos(pi * x)
    a = 0
    b = 0.4
    eps = 1e-12
    expected = 0.5
    try:
        computed = bisect(f, a, b, eps)
    except RecursionError as e:
        print(f"There seems to be no root of f on the interval [{a}, {b}]")
        return

    error = abs(expected - computed)
    tolerance = 1e-12
    success = error < tolerance
    msg = f"""
    Error testing `piecewise`.
    Expected:  {expected}
    Computed:  {computed}
    Error:     {error:13.6e}
    Tolerance: {tolerance:13.6e}"""
    assert success, msg

test_bisect()

答案 1 :(得分:0)

我发现了问题..使用Jupyter Notebook时似乎没有引发异常。我的意思是它是在没有try-except块的情况下引发的,但是有了它,它只能在命令行中运行。