Home > other >  time.sleep(300) not allowing script to stop thread | python |
time.sleep(300) not allowing script to stop thread | python |

Time:09-04

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

CodePudding user response:

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.

CodePudding user response:

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

  • Related