添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
Stack Overflow for Teams is a private, secure spot for you and your coworkers to find and share information. Learn more

A python internals inquiry. Can you gurus please help me understand why the following code leads to a "Fatal python error" rather than nicely catching over the recursion limit overflow?

def flowfunc(x):
        if x < 0:
            flowfunc(x + 3)
            flowfunc(x + 5)
        else:
            flowfunc(x - 1)
    except:
        print("exception at: x = ", x)

Call it with e.g.:

flowfunc(0)

and all breaks loss with

exception at: x =  -1
Fatal Python error: Cannot recover from stack overflow.
[threads data...]

Seems like it all depends on the 2nd recursive call. The following code will behave nicely:

def flowfunc2(x):
        if x < 0:
            flowfunc2(x + 3)
            # flowfunc2(x + 5)
        else:
            flowfunc2(x - 1)
    except:
        print("exception at: x = ", x)
flowfunc2(0)

returning (value may change depending on available stack depth):

exception at: x =  -1

I'm on python 3.6. Your insight will be appreciated.

Similarity between the two snippets:

You have an oscillating recursive function going between positives and negatives, never really terminating. Once you reach the max recursive depth set by Python, you catch the exception, print the current value.

Difference between the two snippets:

In the first version (where you get the fatal error), after printing the max depth reached exception, instead of winding up your call stack, you just go one level-up and call flowfunc(x + 5) piling up even more calls in the call stack than Python can possibly handle. That's where you get the fatal error. In the second version, after printing the exception you just go straight up returning None to the original caller and terminate the execution of your program. In a way, the printing of exception in the second snippet serves as your base case for recursion since there is nothing else to do in the caller and hence your program terminates gracefully.

So yes, your observation is right, it does depend on the second recursive call.

This is the same error as https://bugs.python.org/issue6028.

And the reason is explained there as well: "This is normal behaviour, actually. The RuntimeError is raised, but you catch it in the except clause and then recurse again ad infinitum. The interpreter realizes that it "cannot recover from stack overflow", as the message says, and then bails out."

Basically, because of the existence of your second recursive call, the program continues after the error is caught in your first one and it keeps branching and generates infinite RuntimeError.

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.

site design / logo © 2020 Stack Exchange Inc; user contributions licensed under cc by-sa 4.0 with attribution required. rev 2020.4.3.36492