EasilyBaffled
EasilyBaffled

Reputation: 3882

Python, sleep some code not all

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()

Upvotes: 1

Views: 420

Answers (3)

Jiří Baum
Jiří Baum

Reputation: 6940

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.

Upvotes: 0

AnonymousUser
AnonymousUser

Reputation: 786

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.

Upvotes: 0

pypat
pypat

Reputation: 1116

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

Upvotes: 3

Related Questions