Python, sleep some code not all

Question:

I have a situation, where at some point in my code I want to trigger a number of timers, the code will keep running, but at some point these functions will trigger and remove an item from a given list. Similar though not exactly like the code below. The problem is, I want these functions to wait a certain amount of time, the only way I know how is to use sleep, but that stops all of the code, when I need the first function to keep running. So how can I set a function aside with out making everything wait for it? If the answer involves threading, please know that I have very little experience with it and like explanations with pictures and small words.

from time import sleep
from datetime import datetime
def func():
    x = 1
    for i in range(20):
        if i % 4 == 0:
            func2()
            print("START", datetime.now())
            x += 1
        else:
            print("continue")

def func2():
    print("go")
    sleep(10)
    print("func 2--------------------------------------", datetime.now())
func()
Asked By: EasilyBaffled

||

Answers:

You need to use threading. http://docs.python.org/2/library/threading.html
You can start functions in their own threads.

Answered By: pypat

I used background function. It will run in the background, even if going to another page.


You need to import threading, also time to use time.sleep():

import threading
import time

I had a function where I wanted to sleep code in the background, here is an example:


# This is the one that will sleep, but since you used args on the Thread, it will not make the mainFunction to sleep.
def backgroundFunction(obj):
    theObj = obj
    time.sleep(120)
    # updates the Food to 5 in 2 minutes
    obj["Food"] = 5

    return


def mainFunction():
    obj = {"Food": 4, "Water": 3}

    # Make sure there are a comma in the args(). 
    t1 = threading.Thread(target=backgroundFunction, args=(obj,))
    t1.start()


    return

If you used t1 = threading.Thread(target=backgroundFunction(obj)) it will not be in the background so don’t use this, unless you want mainFunction to sleep also.

Answered By: AnonymousUser

Depending on the situation, another option might be an event queue based system. That avoids threads, so it can be simpler.

The idea is that instead of using sleep(20), you calculate when the event should fire, using datetime.now() + timedelta(seconds=20). You then put that in a sorted list.

Regularly, perhaps each time through the main loop of your program, you check the first element in the list; if the time has passed, you remove it and call the relevant function.

To add an event:

  pending_events.append((datetime.now() + timedelta(seconds=20), e))
  pending_events.sort()

Then, as part of your main loop:

for ... # your main loop

    # handle timed events:
    while pending_events[0][0] < datetime.now():
        the_time, e = pending_events.pop(0)
        handle_event(e, the_time)

    ... # rest of your main loop

This relies on your main loop regularly calling the event-handling code, and on the event-handling code not taking much time to handle the event. Depending on what the main loop and the events are doing, this may come naturally or it may be some effort or it may rule out this method…

Notes:

  • You only need to check the first element in the list, because the list is sorted in time order; checking the first element checks the earliest one and you don’t need to check the others until that one has passed.
  • Instead of a sorted list, you can use a heapq, which is more complicated but faster; in practice, you’d need a lot of pending events to notice any difference.
  • If the event is to be "every 20s" rather than "after 20s", use the_time + timedelta(seconds=20) to schedule each subsequent event; that way, the delay in getting to and processing the event won’t be added.
Answered By: Jiří Baum
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.