我正在尝试构建一个实时项目,其中状态每秒更新一次,因此部分代码会不断重复。当我想更改必须更新的信息时,我只需单击new按钮,这将为我提供第一个窗口,我可以在其中更新新信息。但是这样做给了我以下的错误。如果我使用after()而不是线程,则错误不会出现,但输出窗口会被挂起。请帮助我解决此问题。多谢各位
Exception in thread Thread-2:
Traceback (most recent call last):
File "C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python37_64\lib\threading.py", line 926, in _bootstrap_inner
self.run()
File "C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python37_64\lib\threading.py", line 1177, in run
self.function(*self.args, **self.kwargs)
File "C:/Users/Desktop/Tool/t.py", line 47, in ae
self.treeview.insert('', 'end',image=self._img, value=(a))
File "C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python37_64\lib\tkinter\ttk.py", line 1370, in insert
res = self.tk.call(self._w, "insert", parent, index, *opts)
_tkinter.TclError: invalid command name ".!treeview"
我遇到问题的代码:
def aaa(self):
num_threads = 5 * multiprocessing.cpu_count()
p = multiprocessing.dummy.Pool(num_threads)
p.map(self.ping_func, [x for x in Demo2.t1])
self.process_incoming()
#threading.Timer(1.0, self.aaa).start()-this gives the error while pressing new button and updating information
self.master.after(100, self.aaa) #it hangs the output window
示例代码:
import multiprocessing.dummy
import multiprocessing
import os
import socket
import sys
import subprocess
import re
import time
import threading
import tkinter.messagebox
from tkinter import ttk
import queue
from tkinter import *
class Demo1: #window 1
data=[]
def __init__(self, master):
self.master = master
self.t=tkinter.Text(self.master,height=20,width=50)
self.t.grid(row=1, column=1)
self.button = tkinter.Button(self.master,height=3,width=10, text="OK", command = self.new_window)
self.button.grid(row=2,column=1)
def new_window(self):
self.inputValue=self.t.get("1.0",'end-1c')
Demo1.data=self.inputValue.split("\n")
self.master.destroy() # close the current window
self.master = tkinter.Tk() # create another Tk instance
self.app = Demo2(self.master) # create Demo2 window
self.master.mainloop()
class Demo2: #window 2
value = []
display = []
num=0
def __init__(self, master):
self.master = master
self.queue = queue.Queue()
Demo2.value = Demo1.data
self.button = tkinter.Button(self.master,height=2,width=11, text="new",command=self.new).place(x=0,y=0)
self.label = tkinter.Label(self.master, text="monitor", font=("Arial",20)).grid(row=0, columnspan=3)
cols = ('aa','bb')
self.treeview = ttk.Treeview(self.master, columns=cols)
for col in cols:
self.treeview.heading(col, text=col)
self.treeview.column(col,minwidth=0,width=170)
self.treeview.grid(row=1, column=0)
self._img=tkinter.PhotoImage(file="green1.gif")
self.aaa()
def aaa(self):
num_threads = 5 * multiprocessing.cpu_count()
p = multiprocessing.dummy.Pool(num_threads)
p.map(self.ping_func, [x for x in Demo2.value])
self.process_incoming()
#threading.Timer(1.0, self.aaa).start()
self.master.after(100, self.aaa)
def ping_func(self,ip): #Ping every ip and append the result
ping_result = []
pingCmd = "ping -n 1 -w 1000 " + ip
childStdout = os.popen(pingCmd)
result = (childStdout.readlines())
childStdout.close()
ping_result.append(ip)
if(any('Reply from' in i for i in result)):
ping_result.append("success")
else:
ping_result.append("failed")
self.queue.put(ping_result) #Thread value to queue
def process_incoming(self): #add the ping result to treeview
while self.queue.qsize():
try:
if Demo2.num<len(Demo1.data):
self._img=tkinter.PhotoImage(file="green1.gif")
self._img1=tkinter.PhotoImage(file="red.gif")
msg = self.queue.get_nowait()
Demo2.display.append(msg) #adding queue value to variable(display)
if(len(Demo2.display)==len(Demo1.data)):
self.treeview.insert("","end",values=(0,0,0,0,0))
self.treeview.delete(*self.treeview.get_children())
for i,(a,b) in enumerate(Demo2.display):
if(Demo2.display[i][1]=='success' ):
self.treeview.insert('', 'end',image=self._img, value=(a,b))
else:
self.treeview.insert('', 'end',image=self._img1, value=(a,b))
Demo2.num=Demo2.num+1
Demo2.display.clear()
else:
Demo2.display.clear()
Demo2.num=0
except queue.Empty: # Shouldn't happen.
pass
def periodic_call(self):
self.master.after(200, self.periodic_call) # checking its contents periodically
self.process_incoming()
if not self.running:
import sys
sys.exit(1)
def new(self):
self.master.destroy() # close the current window
self.master = tkinter.Tk() # create another Tk instance
self.app = Demo1(self.master) # create Demo2 window
self.master.mainloop()
def main():
root = tkinter.Tk()
app = Demo1(root)
root.mainloop()
if __name__ == '__main__':
main()
主要问题是
ping -w 1000
需要大量时间运行,但Pool.map()
等待所有结果。您甚至可以在没有queue
的情况下运行results = p.map(...)
(但是使用return result
),但它也可以阻止tkinter
您可以使用
map_async()
运行它,而无需等待结果我还使用
starmap
(或者更确切地说starmap_async()
)向每个进程发送两个参数ip, queue
我还做了其他更改-例如重命名变量,将一些代码移到
__init__
只创建一次(图像,Pool
,Queue
)。我还将IP列表作为参数Window2(master, data)
和参数Window1(master, data)
发送到其他窗口,以便编辑此列表BTW:
因为我在Linux上运行,所以我更改了ping
的参数,并检查不同的文本以测试它是否得到答案相关问题 更多 >
编程相关推荐