In a while True loop, you need to make sure there is a definite point where you break out of the loop, otherwise it will run forever (and crash Rhino). There are a bunch of ways to do this, but you absolutely have to make sure your logic is ironclad and can’t fail.
When testing stuff I usually put in a safety - count the loops and automatically break out if the loop count goes over some number. You can do this by adding a conditional to the while loop:
#do your thing
if count>=1000: print "Safety limit exceeded!"
or in the loop
#do your thing
print "Safety limit exceeded!"
Once you’re sure you are exiting the loop before you hit the safety point, you can remove it.
This doesn’t work @clement. I’ve tried that. After Rhino becomes non-responsive even escape doesn’t work. This only works when used inside Grasshopper and only due to the fact that Grasshopper has a mechanism to stop the calculation on errors.
Hi @ivelin.peychev, i am using this in +200 scripts and it works if ESC is pressed when a new loop starts. It also works in multiprocessed scripts. I asume that you’re code below this line is hanging and therefore you never reach the point (the next loop) where the check for ESC is happening.
It can only check for the key press / hold down if it is not in the middle of something eg. a boolean or split operation. Sometimes it helps if you’re adding a few milliseconds above the key check using rs.Sleep(10). Btw. if you want to cancel the while loop anyway and set it up with a counter, you can just use this:
counter = 0
while counter <1000:
# Do something here
# increase the counter
counter += 1
I’ve tested all of these, but as I said, when rhino gets overloaded to a non-responsive state none of them matter.
There are two options that slightly increase the chance of recovery. One is, as you said above, to pause the PythonInterpreter, the second is to make Rhino wait for one operation to complete before launching the other: Rhino.RhinoApp.Wait()
Something I also try to avoid if possible, but it is the only way to deal with items that are nested to an undetermined depth. There are two situations concerning the Rhino interface that could need this, layers with sublayers and nested blocks. Layers are relatively easy as there is only one type of entity we are dealing with - a layer name or ID - whereas blocks are more complex, as they could contain any number of objects including other blocks.
In any case, it’s a bit difficult to wrap your head around the concept. As the old joke goes-
“In order to understand recursion, you first need to understand recursion”
Basically it’s a subroutine that calls itself (inside itself). If you imagine that a nested list has a structure like a tree with branches, on each loop the script crawls up one branch until it gets to the next one that branches off from it, then goes up that one to the next branch point etc. At some point, the script gets to the end of a twig that has no other branches. That is the critical point. If you don’t have some code in there to detect that you got to the end of a branch structure, it will just stay there and continue to run infinitely (and hang Rhino in this case).
So usually you have a line that says that if no more branches are found in the “up” direction, to break out of the current loop (but not exit the script). That has the effect of pushing the script back down to the previous level and start looking for new branches on that level. When those are all found and done, then it goes back down another level, and so forth. You can see in this way that the entire tree structure is then covered. For example, in the case of parsing a nested layer tree, on every run it would be checking if the current layer has any children. If not, then it needs to break out, as that is the end of that particular branch.
While you are developing this type of stuff, it’s useful to have a small file with only a few elements to test, put in print statements to tell you at what branch level you’re at, and have a safety valve in case you do get stuck in an infinite loop anyway.