Problem rs.sleep computing python

Hello everyone,

I’m trying to use the rs.sleep() function in order to create a time interval between operation for batch rendering purpose.

But when I try to use the rs.sleep() function in a loop, it only works at the end of the whole loop.
For instance I tried the simple script but everything is printed in the same time instead of one line each 2000ms

print “This”
rs.Sleep(2000)
print “is”
rs.Sleep(2000)
print “a”
rs.Sleep(2000)
print “slow”
rs.Sleep(2000)
print “message!”*

Thanks guys!

Welcome @haehnsen,

The problem is that the GHPython component doesn’t recompute at each loop iteration! Instead it runs your script once internally, keeping track of your desired pauses, and then returns the result(s) at the script end. It only updates itself, if it gets externally triggered, by you or an input parameter changing.

What you are trying to do isn’t possible, unless you explicitly control the way the component gets updated:

example

from scriptcontext import sticky
import Grasshopper as gh
import time

def update_component():
    """Updates this component, similar to using a Grasshopper timer."""
    # written by Anders Deleuran (andersholdendeleuran.com)
    def call_back(e):
        """Defines a callback action"""
        ghenv.Component.ExpireSolution(False)
    # Get the Grasshopper document
    ghDoc = ghenv.Component.OnPingDocument() 
    # Schedule this component to expire
    ghDoc.ScheduleSolution(1, \
        gh.Kernel.GH_Document.GH_ScheduleDelegate(call_back))


message_parts = "This is a slow message!".split(" ")

if Reset and "Count" in sticky.keys():
    sticky.pop("Count", None)
    ghenv.Component.Message = "Reset"

if Run:
    if not "Count" in sticky.keys():
        count = 0
        sticky["Count"] = count
        update_component()
    else:
        count = sticky["Count"]
        if count < len(message_parts)-1:
            count += 1
            sticky["Count"] = count
            ghenv.Component.Message = "Running"
            update_component()
        else:
            ghenv.Component.Message = "Finished"
    
    print "{}: {}".format(count, message_parts[count])
    time.sleep(0.5)
1 Like

Thanks P1r4t3b0y!!

It was exactly what I was looking for,

Cheers!

Great solution, thanks P1r4t3b0y!

Just wondering. Is it possible to make it wait for a external (from another component) condition to be met in order to proceed to the next loop, instead of the timer? (sleep).

By the way, here follows a small amendment where the boolean toggle is not necessary:

import scriptcontext as sc
import Grasshopper as gh
import time

def update_component():
    """Updates this component, similar to using a Grasshopper timer."""
    # written by Anders Deleuran (andersholdendeleuran.com)
    def call_back(e):
        """Defines a callback action"""
        ghenv.Component.ExpireSolution(False)
    # Get the Grasshopper document
    ghDoc = ghenv.Component.OnPingDocument() 
    # Schedule this component to expire
    ghDoc.ScheduleSolution(1, \
        gh.Kernel.GH_Document.GH_ScheduleDelegate(call_back))

#Resets the sticky dictionary
if Reset and "list_index" in sc.sticky.keys():
    sc.sticky.pop("list_index", None)
    ghenv.Component.Message = "Reset"
    sc.sticky["run_timed_loop"] = True

if sc.sticky.Contains("run_timed_loop"):
    if sc.sticky["run_timed_loop"]:
        #after reseting, if the sticky dictionary is empty, start counting and putting
        if not "list_index" in sc.sticky.keys():
            count = 0
            sc.sticky["list_index"] = count
            update_component()
        #filter when starts counting (index > 0)
        else:
            count = sc.sticky["list_index"]
            #loop over all list but the last item
            if count < len(list)-1:
                count += 1
                sc.sticky["list_index"] = count
                ghenv.Component.Message = "Running"
                update_component()
            # list last item
            else:
                ghenv.Component.Message = "Finished"
                sc.sticky["run_timed_loop"] = False
        item = list[count]
        time.sleep(time_to_delay)