Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Terminating threads
#1
Question 
The code below runs 3 threads.
how can I stop them (especially print_to_box) without freezing the program?

This is the handler:
    def thread_handler(self, host):

        threads = []

        wt = threading.Thread(target=self.write_to_file, args=(host,))
        pt = threading.Thread(target=self.print_to_box, args=(host,))
        dt = threading.Thread(target=self.delete_default_lines, args=())

        threads.append(wt)
        threads.append(pt)
        threads.append(dt)

        for t in threads:
            t.start()
import tkinter.scrolledtext as scrolledtext
from threading import Lock, Event
import multiprocessing as mp
import subprocess as sub
import tkinter as tk
import threading
import shutil
import signal
import time
import sys
import os
import io


class GUI(tk.Tk):

    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        # self.geometry("860x528")
        self.title("GUI Project")
        self.resizable(0, 0)

        menu = tk.Frame(self, relief="solid")
        container = tk.Frame(self, relief="solid", bg="purple")

        menu.pack(side="left", fill="both", expand=True)
        container.pack(side="right", fill="y", expand=True)

        menu.grid_rowconfigure(0, weight=1)
        container.grid_rowconfigure(0, weight=1)
        container.grid_rowconfigure(1, weight=1)
        container.grid_rowconfigure(2, weight=1)
        container.grid_rowconfigure(3, weight=1)
        container.grid_rowconfigure(4, weight=1)
        container.grid_rowconfigure(5, weight=1)
        container.grid_rowconfigure(6, weight=1)
        container.grid_columnconfigure(0, weight=1)
        container.grid_columnconfigure(1, weight=2)
        container.grid_columnconfigure(2, weight=2)
        container.grid_columnconfigure(3, weight=2)
        container.grid_columnconfigure(4, weight=2)
        container.grid_columnconfigure(5, weight=2)
        container.grid_columnconfigure(6, weight=2)

        self.frames = ["Menu", "CmdCli", "FutureFeature", "FutureFeature2", "FutureFeature3"]

        self.frames[0] = Menu(parent=menu, controller=self)
        self.frames[1] = CmdCli(parent=container, controller=self)
        self.frames[2] = FutureFeature(parent=container, controller=self)
        self.frames[3] = FutureFeature2(parent=container, controller=self)
        self.frames[4] = FutureFeature3(parent=container, controller=self)

        self.frames[0].grid(row=0, column=0, sticky="nsew")
        self.frames[1].grid(row=0, column=0, sticky="nsew")
        self.frames[2].grid(row=0, column=0, sticky="nsew")
        self.frames[3].grid(row=0, column=0, sticky="nsew")
        self.frames[4].grid(row=0, column=0, sticky="nsew")

        self.show_frame(1)

    def show_frame(self, page_name):
        frame = self.frames[page_name]
        print(frame)
        frame.tkraise()
        frame.grid(row=0, column=0, sticky="nsew")


class Menu(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent, bg="black")
        self.controller = controller

        ping_test_button = tk.Button(self, text="CLI CMD", bg="skyblue1", pady=30,
                                     command=lambda: controller.show_frame(1))
        future_feature1_button = tk.Button(self, text="FutureFeature", bg="dark violet", pady=30,
                                           command=lambda: controller.show_frame(2))
        future_feature2_button = tk.Button(self, text="FutureFeature2", bg="pale goldenrod", pady=30,
                                           command=lambda: controller.show_frame(3))
        future_feature3_button = tk.Button(self, text="FutureFeature3", bg="green", pady=30,
                                           command=lambda: controller.show_frame(4))
        app_exit = tk.Button(self, text="Quit", bg="gray40", pady=30,
                             command=lambda: self.terminate())

        ping_test_button.pack(fill="both", expand=True)
        future_feature1_button.pack(fill="both", expand=True)
        future_feature2_button.pack(fill="both", expand=True)
        future_feature3_button.pack(fill="both", expand=True)
        app_exit.pack(fill="both", expand=True)

    @staticmethod
    def terminate():

        while True:
            path = fr'c:/users/{os.getlogin()}/desktop/Gui-Skeleton'

            try:
                shutil.rmtree(path)
                exit()
            except OSError as err:
                print(f"Error Deleting tmp folder! {err}")
                exit()


class CmdCli(tk.Frame):

    file = fr'c:/users/{os.getlogin()}/Desktop/default.txt'
    newfile = fr'c:/users/{os.getlogin()}/Desktop/Gui-Skeleton/default-tmp.txt'
    lastfile = fr'c:/users/{os.getlogin()}/Desktop/logger.txt'

    def __init__(self, parent, controller):

        tk.Frame.__init__(self, parent, bg="skyblue1")
        self.controller = controller

        self.command_label = tk.Label(self, text="Enter Command : ", padx=7, pady=5, bg="skyblue1")
        self.command_input_box = tk.Entry(self)
        self.command_input_box.bind('<Return>', lambda e: self.thread_handler(self.command_input_box.get()))

        self.submit_button = tk.Button(self, text="Submit", width=10, height=1,
                                       command=lambda: self.thread_handler(self.command_input_box.get()))
        self.clear_field_button = tk.Button(self, text="Clear Field", width=10, padx=2,
                                            command=lambda: self.clear_boxes(self.command_input_box))
        self.clear_file_button = tk.Button(self, text="Clear File", width=10,
                                           command=lambda:
                                           open(self.lastfile, 'w+').close())
        self.clear_window_button = tk.Button(self, text="Clear Window", width=10,
                                             command=lambda: self.clean_window())
        self.stop_button = tk.Button(self, text="Stop", padx=20, command=lambda: self.stop_process())

        self.grid_columnconfigure(0, minsize=20, weight=0)
        self.grid_columnconfigure(1, minsize=20, weight=2)
        self.grid_columnconfigure(2, minsize=5, weight=3)
        self.grid_columnconfigure(3, minsize=20, weight=2)
        self.grid_rowconfigure(0, minsize=50, weight=0)
        self.grid_rowconfigure(1, minsize=20, weight=0)
        self.grid_rowconfigure(2, minsize=30, weight=0)
        self.grid_rowconfigure(3, minsize=10, weight=0)
        self.grid_rowconfigure(4, minsize=10, weight=0)
        self.grid_rowconfigure(5, minsize=10, weight=0)

        self.command_label.grid(row=0, column=1, sticky="nsew")
        self.command_input_box.grid(row=1, column=1, sticky="nsew")
        self.clear_window_button.grid(row=3, column=1, sticky="w")
        self.clear_file_button.grid(row=3, column=1, sticky="n")
        self.clear_field_button.grid(row=1, column=1, sticky="e")
        self.submit_button.grid(row=3, column=1, sticky="se")
        self.stop_button.place(x=510, y=106)

        self.text_widget()

    def clear_files(self):
        open(self.file, 'w+').close()

    def text_widget(self):

        self.text_window = tk.scrolledtext.ScrolledText(self, bg="slategray1")
        self.text_window.insert(tk.END, "")
        self.text_window.config(state=tk.NORMAL)
        self.text_window.grid(row=5, column=1, rowspan=3, sticky="nsew")

    def stop_process(self):
        pass


    @staticmethod
    def clear_boxes(url_input):
        url_input.delete(0, "end")

    def clean_window(self):
        self.text_window.delete("1.0", tk.END)
        self.text_window.insert("1.0", ">>")

    def thread_handler(self, host):

        threads = []

        wt = threading.Thread(target=self.write_to_file, args=(host,))
        pt = threading.Thread(target=self.print_to_box, args=(host,))
        dt = threading.Thread(target=self.delete_default_lines, args=())

        threads.append(wt)
        threads.append(pt)
        threads.append(dt)

        for t in threads:
            t.start()

def check_path_and_create_default_txt():

    path = fr'c:/users/{os.getlogin()}/desktop/Gui-Skeleton'
    try:

        if os.path.isdir(path):
            file = open(fr'c:/users/{os.getlogin()}/Desktop/Gui-Skeleton/default-tmp.txt', 'w+')
            file.close()
            pass

        else:
            os.mkdir(path)
            file = open(fr'c:/users/{os.getlogin()}/Desktop/Gui-Skeleton/default-tmp.txt', 'w+')
            file.close()
            pass

    except OSError as err:
        print(f"[!] Operation failed! {err}")


def start_logger_file():

    with open(fr'c:/users/{os.getlogin()}/desktop/logger.txt', 'w+'):
        pass


def main():

    print("Main Gui Thread")

    t2 = threading.Thread(name="Check Path and Create default-tmp",
                            target=check_path_and_create_default_txt, args=())
    t3 = threading.Thread(name="Start Listening File", target=start_logger_file)

    print("Starting Thread: Check Path \n Starting Thread: Listening file")
    t2.start()
    print(threading.get_ident())
    t3.start()
    print(threading.get_ident())

    # check_path_and_create_default_txt()
    # start_logger_file()
    app = GUI()
    app.mainloop()
    app.quit()


if __name__ == "__main__":

    # lock = threading.Lock()
    # lock.acquire()
    t = threading.Thread(name="Main GUI", target=main, args=())
    t.daemon = False
    t.start()
Reply
#2
Among the ways that I know to stop a threading.Thread in python:
  • If the thread is running a loop, it can check now and then if some threading.Event is set and exit the loop if the event is set.
  • A thread can be blocked in an Event.wait() or Lock.wait() or Condition.wait() call. It can be awaken by calling the condition's notify() method for example and then check if some variable tells it to terminate. The wait() functions often have a timeout argument and one can play on this too so that the thread can check regularly if it needs to terminate.
  • A thread can be waiting for I/O operations, for example with a call to select.select(). Again, there are tricks to awaken the thread, for example one can add a socket from a socketpair in the list of files that the select if waiting from and send something in this socket. Once awakened, the thread can check if it must terminate.
  • Similarly, a thread waiting for a selector.Selector instance could use a timeout argument or a similar trick to awake regularly.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Terminating Subprocesses and Threads while they're calculating lvlanson 4 2,450 Oct-17-2020, 12:33 PM
Last Post: lvlanson
  Using Terminating Signal to Terminate Long Threads crcali 1 2,560 Apr-06-2018, 01:26 AM
Last Post: woooee

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020