Ich glaube, dass die Verwirrung von der Differenz zwischen der Stapelgröße, die Sie sehen, wenn der Fehler auftritt, und dem Limit stammt. Die Sache ist, dass der letzte Aufruf, der den Absturz verursacht hat, wahrscheinlich für mehr als 1 Frame auf dem Stack verantwortlich ist, da er selbst einige Funktionsaufrufe durchführt. Und wenn Sie die Ausnahme abfangen, werden der Anruf und seine internen Anrufe bereits aus dem Stapel entfernt. Trotzdem können Sie sie im Traceback sehen. Schauen wir uns das an.
In [1]: import inspect
In [2]: import sys
In [3]: sys.setrecursionlimit(50) # I'm setting this to 50 to make the traceback shorter.
In [4]: stack_log = []
In [5]: def recur():
stack_log.append(len(inspect.stack()))
recur()
...:
In [6]: recur()
Wir bekommen die Rückverfolgung (Note: Es gibt keine Notwendigkeit, es jetzt zu lesen, so bewegen sich nur gespannt auf den nächsten Abschnitt).
---------------------------------------------------------------------------
RecursionError Traceback (most recent call last)
<ipython-input-6-45136123341b> in <module>()
----> 1 recur()
<ipython-input-5-643b16f38b2e> in recur()
1 def recur():
2 stack_log.append(len(inspect.stack()))
----> 3 recur()
4
<ipython-input-5-643b16f38b2e> in recur()
1 def recur():
2 stack_log.append(len(inspect.stack()))
----> 3 recur()
4
<ipython-input-5-643b16f38b2e> in recur()
1 def recur():
2 stack_log.append(len(inspect.stack()))
----> 3 recur()
4
<ipython-input-5-643b16f38b2e> in recur()
1 def recur():
2 stack_log.append(len(inspect.stack()))
----> 3 recur()
4
<ipython-input-5-643b16f38b2e> in recur()
1 def recur():
2 stack_log.append(len(inspect.stack()))
----> 3 recur()
4
<ipython-input-5-643b16f38b2e> in recur()
1 def recur():
2 stack_log.append(len(inspect.stack()))
----> 3 recur()
4
<ipython-input-5-643b16f38b2e> in recur()
1 def recur():
2 stack_log.append(len(inspect.stack()))
----> 3 recur()
4
<ipython-input-5-643b16f38b2e> in recur()
1 def recur():
2 stack_log.append(len(inspect.stack()))
----> 3 recur()
4
<ipython-input-5-643b16f38b2e> in recur()
1 def recur():
2 stack_log.append(len(inspect.stack()))
----> 3 recur()
4
<ipython-input-5-643b16f38b2e> in recur()
1 def recur():
2 stack_log.append(len(inspect.stack()))
----> 3 recur()
4
<ipython-input-5-643b16f38b2e> in recur()
1 def recur():
2 stack_log.append(len(inspect.stack()))
----> 3 recur()
4
<ipython-input-5-643b16f38b2e> in recur()
1 def recur():
2 stack_log.append(len(inspect.stack()))
----> 3 recur()
4
<ipython-input-5-643b16f38b2e> in recur()
1 def recur():
2 stack_log.append(len(inspect.stack()))
----> 3 recur()
4
<ipython-input-5-643b16f38b2e> in recur()
1 def recur():
2 stack_log.append(len(inspect.stack()))
----> 3 recur()
4
<ipython-input-5-643b16f38b2e> in recur()
1 def recur():
2 stack_log.append(len(inspect.stack()))
----> 3 recur()
4
<ipython-input-5-643b16f38b2e> in recur()
1 def recur():
2 stack_log.append(len(inspect.stack()))
----> 3 recur()
4
<ipython-input-5-643b16f38b2e> in recur()
1 def recur():
2 stack_log.append(len(inspect.stack()))
----> 3 recur()
4
<ipython-input-5-643b16f38b2e> in recur()
1 def recur():
2 stack_log.append(len(inspect.stack()))
----> 3 recur()
4
<ipython-input-5-643b16f38b2e> in recur()
1 def recur():
2 stack_log.append(len(inspect.stack()))
----> 3 recur()
4
<ipython-input-5-643b16f38b2e> in recur()
1 def recur():
2 stack_log.append(len(inspect.stack()))
----> 3 recur()
4
<ipython-input-5-643b16f38b2e> in recur()
1 def recur():
2 stack_log.append(len(inspect.stack()))
----> 3 recur()
4
<ipython-input-5-643b16f38b2e> in recur()
1 def recur():
2 stack_log.append(len(inspect.stack()))
----> 3 recur()
4
<ipython-input-5-643b16f38b2e> in recur()
1 def recur():
2 stack_log.append(len(inspect.stack()))
----> 3 recur()
4
<ipython-input-5-643b16f38b2e> in recur()
1 def recur():
2 stack_log.append(len(inspect.stack()))
----> 3 recur()
4
<ipython-input-5-643b16f38b2e> in recur()
1 def recur():
2 stack_log.append(len(inspect.stack()))
----> 3 recur()
4
<ipython-input-5-643b16f38b2e> in recur()
1 def recur():
2 stack_log.append(len(inspect.stack()))
----> 3 recur()
4
<ipython-input-5-643b16f38b2e> in recur()
1 def recur():
2 stack_log.append(len(inspect.stack()))
----> 3 recur()
4
<ipython-input-5-643b16f38b2e> in recur()
1 def recur():
2 stack_log.append(len(inspect.stack()))
----> 3 recur()
4
<ipython-input-5-643b16f38b2e> in recur()
1 def recur():
2 stack_log.append(len(inspect.stack()))
----> 3 recur()
4
<ipython-input-5-643b16f38b2e> in recur()
1 def recur():
----> 2 stack_log.append(len(inspect.stack()))
3 recur()
4
/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/inspect.py in stack(context)
1462 def stack(context=1):
1463 """Return a list of records for the stack above the caller's frame."""
-> 1464 return getouterframes(sys._getframe(1), context)
1465
1466 def trace(context=1):
/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/inspect.py in getouterframes(frame, context)
1439 framelist = []
1440 while frame:
-> 1441 frameinfo = (frame,) + getframeinfo(frame, context)
1442 framelist.append(FrameInfo(*frameinfo))
1443 frame = frame.f_back
/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/inspect.py in getframeinfo(frame, context)
1412 start = lineno - 1 - context//2
1413 try:
-> 1414 lines, lnum = findsource(frame)
1415 except OSError:
1416 lines = index = None
/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/inspect.py in findsource(object)
742 is raised if the source code cannot be retrieved."""
743
--> 744 file = getsourcefile(object)
745 if file:
746 # Invalidate cache if needed.
/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/inspect.py in getsourcefile(object)
670 return filename
671 # only return a non-existent filename if the module has a PEP 302 loader
--> 672 if getattr(getmodule(object, filename), '__loader__', None) is not None:
673 return filename
674 # or it is in the linecache
/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/inspect.py in getmodule(object, _filename)
699 # Try the cache again with the absolute file name
700 try:
--> 701 file = getabsfile(object, _filename)
702 except TypeError:
703 return None
/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/inspect.py in getabsfile(object, _filename)
683 if _filename is None:
684 _filename = getsourcefile(object) or getfile(object)
--> 685 return os.path.normcase(os.path.abspath(_filename))
686
687 modulesbyfile = {}
/Users/ilia/.venvs/py3/bin/../lib/python3.5/posixpath.py in abspath(path)
355 def abspath(path):
356 """Return an absolute path."""
--> 357 if not isabs(path):
358 if isinstance(path, bytes):
359 cwd = os.getcwdb()
/Users/ilia/.venvs/py3/bin/../lib/python3.5/posixpath.py in isabs(s)
61 def isabs(s):
62 """Test whether a path is absolute"""
---> 63 sep = _get_sep(s)
64 return s.startswith(sep)
65
RecursionError: maximum recursion depth exceeded
Was ist mit dem Stapelprotokoll?
In [7]: stack_log[-1]
Out[7]: 39
Okay, wir haben 11 fehlende Frames. Scrollen Sie jetzt den Traceback zum letzten recur
Aufruf, d. H.
<ipython-input-5-643b16f38b2e> in recur()
1 def recur():
2 stack_log.append(len(inspect.stack()))
----> 3 recur()
4
<ipython-input-5-643b16f38b2e> in recur()
1 def recur():
----> 2 stack_log.append(len(inspect.stack()))
3 recur()
4
/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/inspect.py in stack(context)
1462 def stack(context=1):
1463 """Return a list of records for the stack above the caller's frame."""
-> 1464 return getouterframes(sys._getframe(1), context)
1465
1466 def trace(context=1):
/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/inspect.py in getouterframes(frame, context)
1439 framelist = []
1440 while frame:
-> 1441 frameinfo = (frame,) + getframeinfo(frame, context)
1442 framelist.append(FrameInfo(*frameinfo))
1443 frame = frame.f_back
/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/inspect.py in getframeinfo(frame, context)
1412 start = lineno - 1 - context//2
1413 try:
-> 1414 lines, lnum = findsource(frame)
1415 except OSError:
1416 lines = index = None
/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/inspect.py in findsource(object)
742 is raised if the source code cannot be retrieved."""
743
--> 744 file = getsourcefile(object)
745 if file:
746 # Invalidate cache if needed.
/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/inspect.py in getsourcefile(object)
670 return filename
671 # only return a non-existent filename if the module has a PEP 302 loader
--> 672 if getattr(getmodule(object, filename), '__loader__', None) is not None:
673 return filename
674 # or it is in the linecache
/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/inspect.py in getmodule(object, _filename)
699 # Try the cache again with the absolute file name
700 try:
--> 701 file = getabsfile(object, _filename)
702 except TypeError:
703 return None
/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/inspect.py in getabsfile(object, _filename)
683 if _filename is None:
684 _filename = getsourcefile(object) or getfile(object)
--> 685 return os.path.normcase(os.path.abspath(_filename))
686
687 modulesbyfile = {}
/Users/ilia/.venvs/py3/bin/../lib/python3.5/posixpath.py in abspath(path)
355 def abspath(path):
356 """Return an absolute path."""
--> 357 if not isabs(path):
358 if isinstance(path, bytes):
359 cwd = os.getcwdb()
/Users/ilia/.venvs/py3/bin/../lib/python3.5/posixpath.py in isabs(s)
61 def isabs(s):
62 """Test whether a path is absolute"""
---> 63 sep = _get_sep(s)
64 return s.startswith(sep)
65
RecursionError: maximum recursion depth exceeded
Und hier sind, gibt es genau 11 Funktionsaufrufe (die Pfeile auf der linken Seite), dass 11 Frames auf dem Stapel befindet, die entfernt wurden, wenn die Exception ausgelöst wurde.
Es ist ein Schutz gegen einen Stapelüberlauf. Sie können das Rekursionslimit mit 'sys.setrecursionlimit' ändern, aber dies ist gefährlich. – dazzieta
Was geschieht, wenn Sie die Rekursionseinschränkung mit 'sys.setrecursionlimit (limit)' (https://docs.python.org/3/library/sys.html#sys.setrecursionlimit) am Anfang Ihres Codes manuell setzen? Siehe auch http://stackoverflow.com/questions/3323001/maximum-recursion-depth und http://stackoverflow.com/questions/5061582/setting-stacksize-in-a-python-script/16248113#16248113 – linusg
Nur ein Randnotiz. Sie sollten Ihren rekursiven Code nicht korrigieren, indem Sie das Rekursionslimit erhöhen, da dies nicht ladungssicher ist. Wenn Sie Rekursion wirklich wollen, dann verwenden Sie TCO und einen Dekorator, um die Tailaufrufe zu beseitigen (es gibt viele). Oder bleibe bei einer imperativen Alternative. –