Search code examples
pythonmultithreadingpython-3.xbackground-processpython-multithreading

Function constantly running in the background using threading?


I want the following function to run constantly in a loop to simulate random movement of stocks, while the user can use a menu, this means that it has to run in the background. I've tried to do this by using threading, but I just can't get it to work. I'm using the code for a stock simulator, don't know if this is relevant though.

def stockPriceRandomiser(stockPrices):

    length = len(stockPrices)
    count = 0
    while count < length:

        ranNum = randint(0, 1)

        if ranNum == 0:
            loss = randint(90, 99)/100

            stockPrices[count] = stockPrices[count]*loss



        elif ranNum == 1:
            profit = randint(101, 110)/100

            stockPrices[count] = stockPrices[count]*profit

        count = count + 1
    time.sleep(20)
    return stockPrices

stockPrices = [79, 45, 1233, 67, 54, 5000, 7000, 6974]

Solution

  • Your thread should sleep in a loop, not right before it terminates. And it should leave the loop when a flag controlled from the main thread is set or reset. Here is an example:

    # coding=utf-8
    """
    > python stock.py
    Press Ctrl+C to exit
    [86, 52, 1197, 63, 62, 5165, 6481, 7338]
    [86, 52, 1197, 63, 62, 5165, 6481, 7338]
    [86, 52, 1197, 63, 62, 5165, 6481, 7338]
    [101, 55, 1035, 66, 62, 4457, 7172, 6673]
    [101, 55, 1035, 66, 62, 4457, 7172, 6673]
    ^CTerminating...
    """
    from random import random
    from threading import Thread
    from time import sleep
    import signal
    
    
    def stock_price_randomiser(shared_data):
        while shared_data.threads_active:
            prices = shared_data.stock_prices
            for i in xrange(len(prices)):
                coeff = 0.8 + random() * 0.4  # from 0.8 to 1.2
                prices[i] = int(prices[i] * coeff)
            sleep(5)
    
    
    class SharedData(object):
        """Represent an object that is shared between threads"""
        stock_prices = [79, 45, 1233, 67, 54, 5000, 7000, 6974]
        # As soon as this flag turns False all threads should gracefully exit.
        threads_active = True
    
    
    def main():
        shared_data = SharedData()
        randomiser_thread = Thread(target=stock_price_randomiser,
                                   args=(shared_data,))
    
        def handle_sigint(signal, frame):
            print "Terminating..."
            # We don't want to forcibly kill the thread, so we ask it
            # to exit cooperatively.
            shared_data.threads_active = False
    
        signal.signal(signal.SIGINT, handle_sigint)
        print "Press Ctrl+C to exit"
    
        # Start the thread
        randomiser_thread.start()
    
        while shared_data.threads_active:
            print shared_data.stock_prices
            sleep(2)
    
        # Wait for the thread exit
        randomiser_thread.join()
    
    
    if __name__ == "__main__":
        main()
    

    We launch a thread and pass an object that is shared. That object contains stock_prices list and a flag we use to tell both threads when to exit. One thread updates the list, another reads the list in order to display it. When a user presses Ctrl+C, we handle interrupt signal by resetting our flag that makes our threads exit on next loop iteration.

    P.S. The code is for Python 2