import subprocess
import os
import time
from tkinter import *
root=Tk()
textbox=Text(root)
textbox.pack()
def redirector(inputStr):
textbox.insert(INSERT, inputStr)
def address_ping():
'''
DOCSTRING -> Ip addresses in servers.txt are
192.168.0.1 192.168.0.26
'''
while True:
with open('servers.txt', 'r') as f:
for ip in f:
result=subprocess.Popen(["ping", "-c", "7", "-n", "-W", "2", ip],stdout=f, stderr=f).wait()
if result:
print("ip address " + ip, "is inactive")
sys.stdout.write = redirector
else:
print("ip address " + ip, "is active")
sys.stdout.write = redirector
pass
address_ping()
root.mainloop()
我在这里编写了一段代码,它将向IP地址发送ping并返回结果。它在CLI上运行良好,但是我希望使用Tkinter将其“打印”到Text
小部件中。我正在将其发送到Text
小部件GUI上,但只有在中断程序后,它才可见。我想在ping通过循环进行时向GUI文本区域提供滚动输出。
答案 0 :(得分:0)
这里使用多线程的东西似乎可以满足您的要求。主程序被分成一部分来处理QUI和一个单独的workerthread
来管理ping subprocess
,从中收集结果并将其放入定期定期传输的Queue
中到GUI。
它使用time.sleep()
是因为它是在单独的线程中完成的,而该线程使用tkinter 不完成,所以可以。
注意,您似乎可能想在GUI中添加垂直滚动条。
import subprocess
import queue
import threading
import time
import tkinter as tk
class GuiPart:
def __init__(self, master, queue, end_command):
self.queue = queue
self.master = master
self.textbox = tk.Text(root)
self.textbox.pack()
btn = tk.Button(master, text='Quit', command=end_command)
btn.pack(expand=True)
def process_incoming(self):
""" Handle all messages currently in the queue. """
while self.queue.qsize():
try:
info = self.queue.get_nowait()
self.textbox.insert(tk.INSERT, info)
except queue.Empty: # Shouldn't happen.
pass
class ThreadedClient:
""" Launch the main part of the GUI and the worker thread.
periodic_call() and end_application() could reside in the GUI part, but
putting them here keeps all the thread controls in a single place.
"""
def __init__(self, master):
self.master = master
self.queue = queue.Queue()
# Set up the GUI part.
self.gui = GuiPart(master, self.queue, self.end_application)
# Set up the background processing thread.
self.running = True
self.thread = threading.Thread(target=self.workerthread)
self.thread.start()
# Start periodic checking of the queue.
self.periodic_call(200)
def periodic_call(self, delay):
""" Every delay ms process everything new in the queue. """
self.gui.process_incoming()
if not self.running:
sys.exit(1)
self.master.after(delay, self.periodic_call, delay)
# Runs in separate thread - NO tkinter calls allowed.
def workerthread(self):
while self.running:
with open('servers.txt', 'r') as file:
for ip in file:
rc = subprocess.Popen(["ping", "-c", "7", "-n", "-W", "2", ip]).wait()
if rc:
self.queue.put('ip address {} is inactive\n'.format(ip))
time.sleep(1)
def end_application(self):
self.running = False # Stop queue checking.
self.master.quit()
if __name__ == '__main__':
root = tk.Tk()
root.title('Pinger')
client = ThreadedClient(root)
root.mainloop() # Display application window and start tkinter event loop.