Python: Alternating functions every x minutes
Asked Answered
G

4

11

Say if I have four functions as below:

def foo():
    subprocess.Popen('start /B someprogramA.exe', shell=True)

def bar():
    subprocess.Popen('start /B someprogramB.exe', shell=True)

def foo_kill():
    subprocess.Popen('taskkill /IM someprogramA.exe')

def bar_kill():
    subprocess.Popen('taskkill /IM someprogramB.exe')

How can I alternate foo and bar functions to run every, say 30 minutes? Meaning: 1st 30mins - run foo, 2nd 30mins - run bar, 3rd 30mins - run foo, and so on. Each new run should 'kill' the previous thread/func.

I have a countdown timer threads, but not sure how to 'alternate' the functions.

class Timer(threading.Thread):
    def __init__(self, minutes):
        self.runTime = minutes
        threading.Thread.__init__(self)


class CountDownTimer(Timer):
    def run(self):
        counter = self.runTime
        for sec in range(self.runTime):
            #do something           
            time.sleep(60) #editted from 1800 to 60 - sleeps for a minute
            counter -= 1

timeout=30
c=CountDownTimer(timeout)
c.start()

EDIT: My solution with Nicholas Knight's inputs...

import threading
import subprocess
import time

timeout=2 #alternate delay gap in minutes

def foo():
    subprocess.Popen('start /B notepad.exe', shell=True)

def bar():
    subprocess.Popen('start /B calc.exe', shell=True)

def foo_kill():
    subprocess.Popen('taskkill /IM notepad.exe')

def bar_kill():
    subprocess.Popen('taskkill /IM calc.exe')


class Alternator(threading.Thread):
    def __init__(self, timeout):
        self.delay_mins = timeout 
        self.functions = [(foo, foo_kill), (bar, bar_kill)]
        threading.Thread.__init__(self)

    def run(self):
        while True:
            for f, kf in self.functions:
                f()
                time.sleep(self.delay_mins*60)
                kf()

a=Alternator(timeout)
a.start()

Works fine.

Guillemot answered 23/5, 2011 at 17:0 Comment(0)
R
6

You're overcomplicating this.

while True:
    foo()
    time.sleep(1800)
    foo_kill()
    bar()
    time.sleep(1800)
    bar_kill()

Or if you want to easily add more functions later:

functions = [(foo, foo_kill), (bar, bar_kill), ] # Just append more as needed
while True:
    for f, kf in functions:
        f()
        time.sleep(1800)
        kf()
Ralf answered 23/5, 2011 at 17:16 Comment(2)
running outside a thread would limit other codes from executing?Guillemot
@siva: To be clear, I wasn't intending "don't run it in a separate thread", I just meant that you were overcomplicating what was in the thread. Wrapping it in a function and launching it in a thread as you've done is fine.Ralf
N
10

Remember that functions are first-class objects in Python. That means you can store them in variables and containers! One way to do it would be:

funcs = [(foo, foo_kill), (bar, bar_kill)]

def run(self):
    counter = self.runTime
    for sec in range(self.runTime):
        runner, killer = funcs[counter % 2]    # the index alternates between 0 and 1
        runner()    # do something
        time.sleep(1800)
        killer()    # kill something
        counter -= 1
Nebula answered 23/5, 2011 at 17:11 Comment(1)
interesting.. would try this out.Guillemot
R
6

You're overcomplicating this.

while True:
    foo()
    time.sleep(1800)
    foo_kill()
    bar()
    time.sleep(1800)
    bar_kill()

Or if you want to easily add more functions later:

functions = [(foo, foo_kill), (bar, bar_kill), ] # Just append more as needed
while True:
    for f, kf in functions:
        f()
        time.sleep(1800)
        kf()
Ralf answered 23/5, 2011 at 17:16 Comment(2)
running outside a thread would limit other codes from executing?Guillemot
@siva: To be clear, I wasn't intending "don't run it in a separate thread", I just meant that you were overcomplicating what was in the thread. Wrapping it in a function and launching it in a thread as you've done is fine.Ralf
P
2

Use a variable to record which function you ran last time. When the timer fires, run the other function and update the variable.

Photography answered 23/5, 2011 at 17:6 Comment(0)
B
1
import itertools, time

# make sure the function are in the order you want to run them in
# and grouped by the ones that you want to run together
funcs = ((bar_kill, foo), (foo_kill, foo)) 

for func_killer, func in itertools.cycle(funcs)
    func_killer()
    func()
    time.sleep(30 * 60) # pause for 30 minutes

function can be stored in lists in pythons, and you can iterate them using a for loop.

itertools is a module to manipulate iterable such as lists. Here we use cycle to make an infinit loop that will process the functions in the list funcs over and over.

Burnout answered 23/5, 2011 at 18:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.