473,508 Members | 2,370 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Detecting recursion loops

My code does recursion loops through a couple of functions. Due to problematic I/O input this leads sometimes to "endless" recursions and after expensive I/O to the Python recursion exception.
What would be a good method to detect recursion loops and stop it by user-Exception (after N passes or some complex criteria) without passing a recursion counter parameter through all the funcs?

Robert
Nov 29 '06 #1
13 4499

robert wrote:
My code does recursion loops through a couple of functions. Due to problematic I/O input this leads sometimes to "endless" recursions and after expensive I/O to the Python recursion exception.
What would be a good method to detect recursion loops and stop it by user-Exception (after N passes or some complex criteria) without passing a recursion counter parameter through all the funcs?
What about `sys.setrecursionlimit`?

http://docs.python.org/lib/module-sys.html

--
HTH,
Rob

Nov 29 '06 #2
robert wrote:
My code does recursion loops through a couple of functions. Due to problematic I/O input this leads sometimes to "endless" recursions and after expensive I/O to the Python recursion exception.
What would be a good method to detect recursion loops and stop it by user-Exception (after N passes or some complex criteria) without passing a recursion counter parameter through all the funcs?

1. You could catch RuntimeError at the top, check whether it's
recursion depth exception, and raise a user exception if it is.

2. Consider whether you're unwittingly trying to cover up a bug. ISTM
no matter how problematic the input is, you should at least be able to
make progress on it. Are you getting this error because, say, you're
not incrementing a counter somewhere, and thus recalling a function
with the same arguments again?

3. Also consider whether you could rewrite the code to be
non-recursive. Usually when I process input recursively, the input is
allowed to be arbitrarily deeply nested. (In that case I think it
would be a mistake to arbitrarily limit depth.) But it sounds to me
like your input might be inherently non-nestable. If that's the case,
it might be possible to get rid of the recursion altogether, or at
least to put in error checking that detects when input is at an invalid
depth.

4. If those concerns don't apply, and you do need to detect recursion,
I'd suggest using a global dictionary to track function calls. If you
have a function parse_something that you want to track, you could
define a dict like this:

_call_count = { parse_something: 0 }

And change parse_something to adjust its own counter:

def parse_something():
_call_count[parse_something] += 1
check_invalid_recursion()
....
_call_count[parse_something] -= 1

(You could define a decorator to do this more easily; that's left as an
excercise.)

The check_invalid_recursion() function would inspect _call_count and
raise an exception based on any criteria you want.

5. In CPython, you could just inpect the stack frame and look for
duplicated function calls. See the documentation for sys._getframe.
Carl Banks

Nov 29 '06 #3
Hi!

I hope you are not trying to find infinite loops and I simply
misunderstood your question. Because if you are, then forget it (Turing
anyone?)... Infinite loops are impossible to find (minus some few, very
specific situations).

Cf. http://en.wikipedia.org/wiki/Halting_problem

Cheers,

Hugo Ferreira

P.S. Hmmm... It seems I really read it wrong since you define that you
want to stop "(after N passes or some complex criteria)". Anyway I
leave the warning for future generations :)
My code does recursion loops through a couple of functions. Due to problematic I/O input this leads sometimes to "endless" recursions and after expensive I/O to the Python recursion exception.
What would be a good method to detect recursion loops and stop it by user-Exception (after N passes or some complex criteria) without passing a recursion counter parameter through all the funcs?

Robert
Nov 29 '06 #4
Rob Wolfe wrote:
robert wrote:
>My code does recursion loops through a couple of functions. Due to problematic I/O input this leads sometimes to "endless" recursions and after expensive I/O to the Python recursion exception.
What would be a good method to detect recursion loops and stop it by user-Exception (after N passes or some complex criteria) without passing a recursion counter parameter through all the funcs?

What about `sys.setrecursionlimit`?

http://docs.python.org/lib/module-sys.html
That is a low level barrier. I just want to limit a certain recursion call chain.
Nov 29 '06 #5
Carl Banks wrote:
robert wrote:
>My code does recursion loops through a couple of functions. Due to problematic I/O input this leads sometimes to "endless" recursions and after expensive I/O to the Python recursion exception.
What would be a good method to detect recursion loops and stop it by user-Exception (after N passes or some complex criteria) without passing a recursion counter parameter through all the funcs?


1. You could catch RuntimeError at the top, check whether it's
recursion depth exception, and raise a user exception if it is.
thats what happens now anyway. need to limit this kind of recursion.
2. Consider whether you're unwittingly trying to cover up a bug. ISTM
no matter how problematic the input is, you should at least be able to
make progress on it. Are you getting this error because, say, you're
not incrementing a counter somewhere, and thus recalling a function
with the same arguments again?
the "bug" comes in from the I/O input. its about to stop it in non-simple recursion (through more functions calls)
3. Also consider whether you could rewrite the code to be
non-recursive. Usually when I process input recursively, the input is
allowed to be arbitrarily deeply nested. (In that case I think it
would be a mistake to arbitrarily limit depth.) But it sounds to me
like your input might be inherently non-nestable. If that's the case,
it might be possible to get rid of the recursion altogether, or at
least to put in error checking that detects when input is at an invalid
depth.

4. If those concerns don't apply, and you do need to detect recursion,
I'd suggest using a global dictionary to track function calls. If you
have a function parse_something that you want to track, you could
define a dict like this:

_call_count = { parse_something: 0 }

And change parse_something to adjust its own counter:

def parse_something():
_call_count[parse_something] += 1
check_invalid_recursion()
....
_call_count[parse_something] -= 1

(You could define a decorator to do this more easily; that's left as an
excercise.)

The check_invalid_recursion() function would inspect _call_count and
raise an exception based on any criteria you want.
thats possibly the right practical/fast possibility, I end so far with. As its threaded, a try-finally protected counter on a TLS _func_recccount[thread.get_ident()]
5. In CPython, you could just inpect the stack frame and look for
duplicated function calls. See the documentation for sys._getframe.
Carl Banks
Nov 29 '06 #6

robert wrote:
>
the "bug" comes in from the I/O input.
Have you considered checking your input for valid values?

Cheers,
John

Nov 29 '06 #7
robert <no*****@no-spam-no-spam.invalidwrites:
Carl Banks wrote:
2. Consider whether you're unwittingly trying to cover up a bug.
ISTM no matter how problematic the input is, you should at least
be able to make progress on it. Are you getting this error
because, say, you're not incrementing a counter somewhere, and
thus recalling a function with the same arguments again?

the "bug" comes in from the I/O input.
If a program doesn't gracefully deal with bad input, that's a bug in
the program. You should be designing your input handler so that it
will do something helpful (even if that's to stop immediately with an
informative error message) in the event of bad input, rather than
allowing that bad data to send your program into an endless loop.

--
\ "People's Front To Reunite Gondwanaland: Stop the Laurasian |
`\ Separatist Movement!" -- wiredog, http://kuro5hin.org/ |
_o__) |
Ben Finney

Nov 29 '06 #8
Ben Finney wrote:
robert <no*****@no-spam-no-spam.invalidwrites:
>Carl Banks wrote:
>>2. Consider whether you're unwittingly trying to cover up a bug.
ISTM no matter how problematic the input is, you should at least
be able to make progress on it. Are you getting this error
because, say, you're not incrementing a counter somewhere, and
thus recalling a function with the same arguments again?
the "bug" comes in from the I/O input.

If a program doesn't gracefully deal with bad input, that's a bug in
the program. You should be designing your input handler so that it
will do something helpful (even if that's to stop immediately with an
informative error message) in the event of bad input, rather than
allowing that bad data to send your program into an endless loop.

Yet that detection is what the asked alg should do. Example: When a HTML-(content)-relaying sends you around in a circle through a complex handler chain.

Robert
Dec 1 '06 #9
On 2006-12-01, robert <no*****@no-spam-no-spam.invalidwrote:
Ben Finney wrote:
>robert <no*****@no-spam-no-spam.invalidwrites:
>>Carl Banks wrote:
2. Consider whether you're unwittingly trying to cover up a bug.
ISTM no matter how problematic the input is, you should at least
be able to make progress on it. Are you getting this error
because, say, you're not incrementing a counter somewhere, and
thus recalling a function with the same arguments again?
the "bug" comes in from the I/O input.

If a program doesn't gracefully deal with bad input, that's a bug in
the program. You should be designing your input handler so that it
will do something helpful (even if that's to stop immediately with an
informative error message) in the event of bad input, rather than
allowing that bad data to send your program into an endless loop.


Yet that detection is what the asked alg should do. Example:
When a HTML-(content)-relaying sends you around in a circle
through a complex handler chain.
Being in a cycle doesn't actually prove your program will never
halt for that particular input, does it?

--
Neil Cerutti
Customers who consider our waitresses uncivil ought to see the manager --sign
at New York restaurant
Dec 1 '06 #10
robert wrote:
Ben Finney wrote:
robert <no*****@no-spam-no-spam.invalidwrites:
Carl Banks wrote:
2. Consider whether you're unwittingly trying to cover up a bug.
ISTM no matter how problematic the input is, you should at least
be able to make progress on it. Are you getting this error
because, say, you're not incrementing a counter somewhere, and
thus recalling a function with the same arguments again?
the "bug" comes in from the I/O input.
If a program doesn't gracefully deal with bad input, that's a bug in
the program. You should be designing your input handler so that it
will do something helpful (even if that's to stop immediately with an
informative error message) in the event of bad input, rather than
allowing that bad data to send your program into an endless loop.


Yet that detection is what the asked alg should do.
Example: When a HTML-(content)-relaying sends
you around in a circle through a complex handler chain.
You might find some engineering inspiration in CherryPy's
InternalRedirect handler [1], which simply raises an error if you visit
the same state twice. Another option is to periodically check a
timeout, which CherryPy does via an Engine.monitor thread [2] (that
runs Response.check_timeout [3]). Note that either approach requires
some alteration to the code being inspected.
Robert Brewer
System Architect
Amor Ministries
fu******@amor.org

[1]
http://www.cherrypy.org/browser/tags...ypy/_cpwsgi.py
[2]
http://www.cherrypy.org/browser/tags...engine.py#L240
[3]
http://www.cherrypy.org/browser/tags...equest.py#L565

Dec 1 '06 #11
Neil Cerutti wrote:
On 2006-12-01, robert <no*****@no-spam-no-spam.invalidwrote:
>Ben Finney wrote:
>>robert <no*****@no-spam-no-spam.invalidwrites:

Carl Banks wrote:
2. Consider whether you're unwittingly trying to cover up a bug.
ISTM no matter how problematic the input is, you should at least
be able to make progress on it. Are you getting this error
because, say, you're not incrementing a counter somewhere, and
thus recalling a function with the same arguments again?
the "bug" comes in from the I/O input.
If a program doesn't gracefully deal with bad input, that's a bug in
the program. You should be designing your input handler so that it
will do something helpful (even if that's to stop immediately with an
informative error message) in the event of bad input, rather than
allowing that bad data to send your program into an endless loop.

Yet that detection is what the asked alg should do. Example:
When a HTML-(content)-relaying sends you around in a circle
through a complex handler chain.

Being in a cycle doesn't actually prove your program will never
halt for that particular input, does it?
not. but its not about a theoretical prove. in practice with same state it goes through the same function here.. I had simply had situations where a server looped my client on to a Python (long through a couple of func-calls) recursion error .

thus, either I fiddle a recursion/counter parameter through my calls, or I do complex state detection as e.g. to copy that of cherrypy was recommend in other post.
Or: I simply throw a hammer at an n-th recursion, wereby I programm the counter locally as simple counter in a "global" thread-local-storage as I wrote.(also possible to use the same counter/limit in multiple functions!)
There were just 2 lines of code to add.
Robert

Dec 1 '06 #12

robert wrote:
My code does recursion loops through a couple of functions. Due to problematic I/O input this leads sometimes to "endless" recursions and after expensive I/O to the Python recursion exception.
What would be a good method to detect recursion loops and stop it by user-Exception (after N passes or some complex criteria) without passing a recursion counter parameter through all the funcs?
Could you not store a set/list of nodes/points already visited and do
an early return if they recur ?

Fuzzyman
http://www.voidspace.org.uk/python/index.shtml
Robert
Dec 1 '06 #13
Instead of threading a counter ( or an accumulator as for
tail-recursive functions ) you can monitor the behaviour of the mutual
recusive function call using an external stack and wrap the
contributing functions using a decorator s.t. pushing and popping to
and from the stack are pre- and postprocessing steps. Since the
external stack is under your control you can define fine grained limits
and actions.

Dec 2 '06 #14

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

12
2737
by: da Vinci | last post by:
Greetings. I want to get everyone's opinion on the use of recursion. We covered it in class tonight and I want a good solid answer from people in the "know" on how well recursion is accepted...
3
4677
by: csx | last post by:
Hi all, Ive got a problem with recursion in Javascript. For this tree: http://www.pcm.uklinux.net/structure.jpg If you input node 3 (i.e. C) which is represented as 'values' in the array, it...
6
4196
by: Thomas Mlynarczyk | last post by:
Hi, Say I have an array containing a reference to itself: $myArray = array(); $myArray =& $myArray; How can I, looping iteratively through the array, detect the fact that $myArray will "take"...
43
4119
by: Lorenzo Villari | last post by:
I've tried to transform this into a not recursive version but without luck... #include <stdio.h> void countdown(int p) { int x;
2
1796
by: andrew browning | last post by:
if i write a function to find the max value of an array and want to write it recursively, how do i decide on the base case? i want to say: if (index 0 is the only index then it is max)...
75
5541
by: Sathyaish | last post by:
Can every problem that has an iterative solution also be expressed in terms of a recursive solution? I tried one example, and am in the process of trying out more examples, increasing their...
10
3762
by: MakeMineScotch | last post by:
What's the secret to writing recursive functions that won't crash the computer?
13
2889
by: Mumia W. | last post by:
Hello all. I have a C++ program that can count the YOYOs that are in a grid of Y's and O's. For example, this Y O Y O O Y O Y O Y O O Y O Y Y O Y O Y O O Y O O Y Y O Y O
30
8266
by: Jeff Bigham | last post by:
So, it appears that Javascript has a recursion limit of about 1000 levels on FF, maybe less/more on other browsers. Should such deep recursion then generally be avoided in Javascript?...
0
7224
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
7323
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
1
7038
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
7493
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
4706
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
3192
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
3180
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
763
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
415
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.