getrecursiondepth

Andrew Dalke adalke at mindspring.com
Sun Sep 26 19:45:38 CEST 2004


Manlio Perillo wrote:
> 1) To write code that execute once in a function (as C static
> variables)
> 2) To guard against too many recursion

Here's a way to get 1).  (And I don't know how
checking the stack depth can be used to emulate
C's static variable.)

def spam(x):
   if spam.first_time:
     spam.first_time = 0
     spam.data = read_data_file("blah.dat")
   return spam.data.compute(x)

spam.first_time = 1

Or without the post-definition initialization

def spam(x):
   if not hasattr(self, "data"):
     spam.data = read_data_file("blah.dat")
   return spam.data.compute(x)

"2) To guard against too many recursion"?  You
could catch the RuntimeError.  Though there
are several things that can raise that error.

 >>> for x in d.iterkeys():
...   if x == "t": del d["p"]
...
Traceback (most recent call last):
   File "<stdin>", line 1, in ?
RuntimeError: dictionary changed size during iteration
 >>>

You could check the exception's data to see
if it contains the string 'maximum recursion
depth exceeded' except that exception messages
isn't guaranteed to be the same on different
versions of Python.  Looking at the code I should
be able to get "maximum recursion depth
exceeded in cmp" but I can't seem to force
that string.

Regexps can cause a recursion limit problem.
Turns out its error message is "maximum recursion
limit exceeded" so a slightly different message.

Should there be a specific exception type for
when the stack limit is exceeded?

In any case, what you're saying is that you
want to take over control of how to limit
Python's stack use.  This means you'll have
your own stack check and your own way to
set the limit.  That makes it harder for anyone
to use your code because they have to understand
that as well.

It also means you can't call someone else's
code because you don't know how that might
affect the stack.  If you don't call someone
else's code then you can always track your
stack use yourself by passing a stack depth
value into your recursion

def my_function(x, y, z, max_depth = 20):
   if max_depth == 0: raise RuntimeError( ....)
   ...
     my_function(x-1,y+3,z/2, max_depth-1)
   ...

That is a more common way to solve your problem.

>> Unlike getrecursionlimit it is something that can be
>>calculated pretty easily.
>>
> 
> I think getrecursiondepth is easy to calculate!

True, and I feel somewhat silly in retrospect for
having said that.  For some reason I was thinking
of a non-recusive way to get that information.

> Wait!
> I have said that the real getrecursiondepth 'redefines' the origin, so
> that outside any function it always returns 0.

Ahh, I see your point.  But then you don't know
how much stack space you have available.  What
if the shell was 900 deep so only 100 was available
to what it executes.   Your software will assume
the stack depth is small (because it ignores the
shell's depth), see the normal stack size of 1000,
so wrongly assume it has that much available.

BTW,  I can fool your code

def fool_recusion_base(n=950):
   if n == 0:
     import pystate
     return
   fool_recursion_base(n-1)

fool_recursion_base()
import pystate
print pystate.getrecursiondepth()


This will probably print a number near -950.

To summarize, I don't see how your solution helps
you with #1 and think there are better ways to
handle #2.  Could you post code to show how you
would use your new function?

				Andrew
				dalke at dalkescientific.com



More information about the Python-list mailing list