pythonlinuxmultithreading

How to stop a terminal process running code including threading?


I am using threading to run multiple functions at the same time with the purpose of pulling weather data from multiple websites. I ran these these programs through the Linux terminal, however am unable to cancel them by pressing ctrl C. I want to have them run for an indefinite amount of time, and as such do not want to add in a finish time, but would rather cancel them when necessary. Does anyone know why ctrl C is not cancelling them, and how to fix this?


Solution

  • Daemon Threads

    It may be tempting to simply use daemon threads to solve this problem, a python execution will stop when only daemon threads are left, and will not allow them to clean up nicely. The docs call this out clearly:

    Daemon threads are abruptly stopped at shutdown. Their resources (such as open files, database transactions, etc.) may not be released properly. If you want your threads to stop gracefully, make them non-daemonic and use a suitable signalling mechanism such as an Event.

    Let's follow their advice and use an Event.

    Using an Event

    An event is a simple flag that can safely be set and read across threads. In this case, we will create an event in the main thread, spawn a new thread to do some work, and listen to that event flag in case it should stop working.

    import threading
    
    ended = threading.Event()
    
    def do_work():
        while not ended.is_set():
            # Do your repeated work
            pass
    
    # Let's create and start our worker thread!
    new_thread = threading.Thread(target=do_work)
    new_thread.start()
    
    try:
        while not ended.is_set():
            ended.wait(1)
    except (KeyboardInterrupt, SystemExit):
        print("Cancelling")
        ended.set()
    

    The try/catch block here runs in the main thread, listening for a KeyboardInterrupt or SystemExit exception. If it catches one, it will set the stopped flag, allowing the thread to complete its current loop iteration, and perform any cleanup it needs to.