Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Time delay loop in python

Tags:

python

i have

for i in xrange(repeat):
  #does my stuff
  time.sleep(10)

BUT, i don't want it to sleep if it's the last run. Meaning, if there's no more iteration, don't sleep

How do I gracefully handle this?

like image 332
user1008636 Avatar asked May 26 '26 04:05

user1008636


1 Answers

case of 1x repetition: doStuff
case of 2x repetition: doStuff, sleep, doStuff
case of 3x repetition: doStuff, sleep, doStuff, sleep, doStuff
...

What you seem to want is to do a bunch of things, then sleep between each of them.

Furthermore, the delay is independent of the nature of the tasks.


Solution 1 -- Sleep if it isn't the last

The easiest way is to special-case the for loop:

for i in range(numTimesToRepeat):
    if i>0:
        time.sleep(lengthToSleep)
    doStuff()

You could also do the following, but it's much less elegant because you repeat doStuff():

doStuff()
for i in range(numTimesToRepeat-1):
    time.sleep(lengthToSleep)
    doStuff()

Solution 2 -- While loop with break

One of the most straightforward ways to solve these issues is to break out of a while loop. It's dirty and somewhat non-functional-programming, but it's very much how a human might naturally think of the problem:

numTimesToRepeat = ...
while True:
    doStuff()                     # we did stuff
    numTimesToRepeat -= 1         # repeat one less time because we just did it
    if numTimesToRepeat==0:       # do we repeat again?
        break                     #   no -> done!
    else:
        time.sleep(lengthToSleep) #   yes -> sleep before repeating

While loops are annoying because if you make a programming error, your program will infinite-loop.


Solution 3 -- Detect if last

The above methods do something if it's not the first iteration of the loop. However, "detecting the last iteration of the loop" is how you tried to approach the problem. It is a bit more annoying, but you can do it like this: https://stackoverflow.com/a/6090673/711085 and use it like this:

for i,task,isLast in enumerateLast(tasks):
    task()
    if not isLast:
        time.sleep(lengthToSleep)

Less elegant is to reverse the list and do enumerate():

for untilLast,task in reversed(enumerate(reversed(tasks))):
    task()
    if untilLast>0:
        time.sleep(lengthToSleep)

(very small irrelevant minutiae: do note that in the reversed(enumerate(reversed(iterable))) case, if tasks were a generator, it would generate every single task to do, enumerate them in reverse order, then do them: this can cause lag, and also prevents you from creating an infinite task generator)


Task abstraction

No matter which way you do it, you may wish to abstract the concept of having tasks by creating callbacks, into which you insert a delay between each, sort of like a ''.join.

def callAndWaitBetween(tasks):
    for ..task.. in enumerate?(tasks):
        #... some solution to this problem...
        task()

For reference, if the delay depended on the tasks, then your tasks should return how long to wait.

like image 114
ninjagecko Avatar answered May 27 '26 17:05

ninjagecko



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!