I have some working code that opens a gui and allows you to enter details for a network ping. There is then a switch to make it a constant ping.
This all works fine. (thanks to another thread here haha).
I’m hoping someone can help me with figuring out how to configure the other button to stop that constant ping without closing the gui. (it may not be possible).
My code is:
import customtkinter
import os
customtkinter.set_appearance_mode("Dark") # Modes: "System" (standard), "Dark", "Light"
customtkinter.set_default_color_theme("blue") # Themes: "blue" (standard), "green", "dark-blue"
class App(customtkinter.CTk):
def __init__(self):
super().__init__()
# configure window
self.title("STEVE's IRT TOOL")
self.geometry(f"{1100}x{580}")
self.resizable(False, False)
self.iconbitmap('icon.ico')
# configure grid layout (4x4)
self.grid_columnconfigure(1, weight=1)
self.grid_columnconfigure((2, 3), weight=0)
self.grid_rowconfigure((0, 1, 2), weight=1)
def read_output(fp):
line = fp.readline()
if line:
print_out.insert("end", line)
print_out.see("end")
print_out.after(10, read_output, fp)
def button_ping():
hostname = info.get()
fp = os.popen(f"ping {switch_var.get()} {hostname}")
read_output(fp)
#def stop():
# create sidebar frame with widgets
self.sidebar_frame = customtkinter.CTkFrame(self, width=140, corner_radius=0)
self.sidebar_frame.grid(row=0, column=0, rowspan=4, sticky="nsew")
self.sidebar_frame.grid_rowconfigure(4, weight=1)
self.logo_label = customtkinter.CTkLabel(self.sidebar_frame, text="IRT Tool", font=customtkinter.CTkFont(size=20, weight="bold"))
self.logo_label.grid(row=0, column=0, padx=20, pady=(20, 10))
info = customtkinter.CTkEntry(self.sidebar_frame, placeholder_text="Enter Input")
info.grid(row=1, column=0, padx=20, pady=10)
sidebar_button_ping = customtkinter.CTkButton(self.sidebar_frame, text="Ping", fg_color="transparent", border_width=2, text_color=("gray10", "#DCE4EE"), command=button_ping)
sidebar_button_ping.grid(row=2, column=0, padx=20, pady=10)
switch_var = customtkinter.StringVar(value="")
switch = customtkinter.CTkSwitch(self.sidebar_frame, text="Constant", variable=switch_var, onvalue="-t", offvalue="")
switch.grid(row=3, column=0, padx=20, pady=10)
sidebar_button_stop = customtkinter.CTkButton(self.sidebar_frame, text="StopPing", fg_color="transparent", border_width=2, text_color=("gray10", "#DCE4EE"))#, command=stop)
sidebar_button_stop.grid(row=4, column=0, padx=20, pady=10)
self.appearance_mode_label = customtkinter.CTkLabel(self.sidebar_frame, text="Appearance Mode:", anchor="w")
self.appearance_mode_label.grid(row=9, column=0, padx=20, pady=(10, 0))
self.appearance_mode_optionemenu = customtkinter.CTkOptionMenu(self.sidebar_frame, values=["Light", "Dark", "System"],
command=self.change_appearance_mode_event)
self.appearance_mode_optionemenu.grid(row=10, column=0, padx=20, pady=(10, 10))
# OUTPUT WINDOW
print_out = customtkinter.CTkTextbox(self, width=250)
print_out.grid(row=0, rowspan=2, column=1, padx=(20, 0), pady=(20, 0), sticky="nsew")
def change_appearance_mode_event(self, new_appearance_mode: str):
customtkinter.set_appearance_mode(new_appearance_mode)
def sidebar_button_event(self):
print("sidebar_button click")
if __name__ == "__main__":
app = App()
app.mainloop()
Many thanks in advance.
>Solution :
Use subprocess.Popen() instead of os.popen(), then you can call proc.terminate() to stop the process. proc is the object returned by subprocess.Popen().
import subprocess as subp
...
class App(customtkinter.CTk):
def __init__(self):
...
def read_output(proc):
line = proc.stdout.readline()
if line:
print_out.after(10, read_output, proc)
else:
line = "--- done ---\n"
print_out.insert("end", line)
print_out.see("end")
def button_ping():
hostname = info.get().strip()
if hostname:
self.proc = subp.Popen(f"ping {switch_var.get()} {hostname}",
stdout=subp.PIPE, stderr=subp.STDOUT,
text=True, bufsize=1)
read_output(self.proc)
def stop():
if self.proc:
self.proc.terminate()
self.proc = None
self.proc = None
...
sidebar_button_stop = customtkinter.CTkButton(self.sidebar_frame, text="StopPing", fg_color="transparent",
border_width=2, text_color=("gray10", "#DCE4EE"), command=stop)
...