I have a working UI that I can initiate a ping command with. In the UI I have an output window. Currently when I click the button to ping there is a small delay and the ping responses then show in the output window. I'm wondering if there is a way to have the responses appear in realtime? Especially for something like a trace route where each hop will appear.
This is the ping code:
def button_ping():
hostname = info.get()
response = os.popen("ping " + hostname).readlines()
print_out.delete("1.0", "end")
print_out.insert("end-1c",response)
Entire code is:
import tkinter
from tkinter import *
from tkinter import messagebox
from tkinter.ttk import *
from tkinter.scrolledtext import ScrolledText
import subprocess
import requests
import urllib3
import os
import re
from requests.auth import HTTPBasicAuth
def button_ping():
hostname = info.get()
response = os.popen("ping " + hostname).readlines()
print_out.delete("1.0", "end")
print_out.insert("end-1c",response)
#GUI SECTION
#WINDOW PARAMETERS
root = Tk()
root.title("Steve's Network Tool")
#root.iconbitmap('icon.ico')
root.geometry("550x550")
root.resizable(False, False)
#WINDOW MENU OPTIONS
def about():
messagebox.showinfo('Version History', 'Version 1.0 Test Edition')
menubar = Menu(root)
file = Menu(menubar, tearoff=0)
file.add_command(label="Exit", command=root.quit)
menubar.add_cascade(label="File", menu=file)
help = Menu(menubar, tearoff=0)
help.add_command(label="About", command=about)
menubar.add_cascade(label="Help", menu=help)
#INPUT FIELDS - PASSWORD CHARACTERS REPLACED WITH '*'
#LEFT FRAME
frame0 = Frame(root)
frame0.grid(row=1)
tkinter.Label(frame0, text="Enter Input:").grid(row=1)
info = tkinter.Entry(frame0)
info.grid(row=1, column=1)
root_label = tkinter.Label(frame0, text="Network Tasks:", pady=5)
root_label.grid(row=3, column=3)
#NETWORK BUTTONS - ROW3
#GET DEVICE ID
button_get_id = Button(frame0, text="Ping", command=button_ping)
button_get_id.grid(row=3, column=4, padx=0)
#DELETE ID
#button_delete_id = Button(frame0, text="Trace", command=button_trace)
#button_delete_id.grid(row=3, column=5, padx=0)
#ACTION BUTTONS & OUTPUT WINDOW
#FRAME3
frame3 = Frame(root)
frame3.grid(row=9, pady=10)
#OUTPUT WINDOW
print_out = ScrolledText(frame3, height=20, width=50, bg="Black", fg='yellow')
print_out.grid(row=3, column=1)
#Copy Text Button
def copy_text_to_clipboard():
#root.clipboard_clear() # clear clipboard contents
root.clipboard_append(print_out.get("1.0", tkinter.END).rstrip()) # append new value to clipboard
#COPY TO CLIPBOARD BUTTON
button_copy = Button(frame3, text="Copy To Clipboard", command=copy_text_to_clipboard)
button_copy.grid(row=11, column=1)
#CLEAR OUTPUT WINDOW
def clear():
print_out.delete("1.0","end")
button_copy = Button(frame3,text="Clear Output", command=clear)
button_copy.grid(row=12, column=1)
#EXIT PROGRAM BUTTON
button_quit = Button(frame3, text="Exit", command=root.quit)
button_quit.grid(row=13, column=1)
root.config(menu=menubar)
root.mainloop()
Many thanks in advance
You can use after loop (using .after()
) to read the output line by line and insert the output into the text box:
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 {hostname}")
read_output(fp)
Note that it is recommended to use subprocess.Popen()
instead of os.popen()
.