skip to Main Content

I am writing a code to insert data to mongodb every 5 minutes ON and OFF

The problem here is on keyword interrupt my thread should be stop and exit the code execution

Once first record is inserted to DB my time.sleep(300) will make the script sleep
and on my terminal the following line appears -> Press enter to kill the running thread :

Incase If I change my mind don’t want to run

simply when I press enter from keyboard the threading which is running and under sleep should be stop and exit

My goal is to stop the thread on the basis of input from user

My code :

import datetime
import threading
import pymongo
import time
from pymongo import MongoClient

dbUrl = pymongo.MongoClient("mongodb://localhost:1245/")
dbName = dbUrl["student"]
dbCollectionName = dbName["student_course"]


def doremon():
    return "Hi Friends"

def insert_to_mongodb():
    global kill_the_running_thread
    while (not kill_the_running_thread):
        note_start_time = datetime.datetime.now()
        msg = doremon()
        note_end_time = datetime.datetime.now()
        dt = {"message": msg, "start_time": note_start_time, "end_time": note_end_time}
        rec_id1 = dbCollectionName.insert_one(dt)
        time.sleep(300)

def main():

    global kill_the_running_thread
    kill_the_running_thread = False
    my_thread = threading.Thread(target=insert_to_mongodb)
    my_thread.start()

    input("Press enter to kill the running thread : ")
    kill_the_running_thread = True

# Calling main
main()

2

Answers


  1. You can try customizing the class, like this:

    import datetime
    import threading
    import pymongo
    import time
    from pymongo import MongoClient
    
    dbUrl = pymongo.MongoClient("mongodb://localhost:1245/")
    dbName = dbUrl["student"]
    dbCollectionName = dbName["student_course"]
    
    
    class ThreadWithKill(threading.Thread):
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            self._target = kwargs.get('target')
            self._kill = threading.Event()
            self._sleep_duration = 300  # 5 minutes
    
        def run(self):
            while True:
                # If no kill signal is set, sleep for the duration of the interval.
                # If kill signal comes in while sleeping, immediately wake up and handle
    
                self._target()  # execute passed function
    
                is_killed = self._kill.wait(self._sleep_duration)
                if is_killed:
                    break
    
        def kill(self):
            self._kill.set()
    
    
    def doremon():
        return "Hi Friends"
    
    
    def insert_to_mongodb():
        note_start_time = datetime.datetime.now()
        msg = doremon()
        note_end_time = datetime.datetime.now()
        dt = {"message": msg, "start_time": note_start_time, "end_time": note_end_time}
        rec_id1 = dbCollectionName.insert_one(dt)
    
    
    def main():
        my_thread = ThreadWithKill(target=insert_to_mongodb)
        my_thread.start()
        input("Press enter to kill the running thread : ")
        my_thread.kill()
    
    if __name__ == "__main__":
        main()
    

    This way there is no need for the kill_the_running_thread variable.
    You’ll need to test this yourself, because I don’t have mongodb.

    Login or Signup to reply.
  2. There’s a problem when using globals as sentinels in conjunction with sleep. The issue is that the sleep may have only just started (5 minutes in OP’s case) and so it could take nearly 5 minutes for the thread to realise that it should terminate.

    A preferred (by me) technique is to use a queue. You can specify a timeout on a queue and, of course, it will respond almost immediately to any data passed to it. Here’s an example:

    from threading import Thread
    from queue import Queue, Empty
    
    def process(queue):
        while True:
            try:
                queue.get(timeout=5)
                break
            except Empty as e:
                pass
            print('Doing work')
    
    
    queue = Queue()
    thread = Thread(target=process, args=(queue,))
    thread.start()
    input('Press enter to terminate the thread: ')
    queue.put(None)
    thread.join()
    

    The process() function will block on the queue for up to 5 seconds (in this example). If there’s nothing on the queue it will do its work. If there is something (we just pass None as the trigger), it will terminate immediately

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search