我正在使用TKinter为python程序im制作绘制一个GUI,我让它在大约200ms时更新,但是当程序查询数据时,它会锁定程序,因为它需要一秒钟才能获取数据。我尝试将其写入多处理中,以便每个查询都是自己的进程,并且只与全局变量共享信息,因为我的程序是一个使用 wmi 获取性能数据的实时程序。至少到目前为止我是这样。不是最终目标,只是开始。因此,如果您能帮助我弄清楚为什么即使使用多处理,如果我在屏幕上拖动应用程序时查询信息,它也会冻结一秒钟。
import wmi
import time
import Tkinter as tk
from multiprocessing import cpu_count
import Image
from PIL import ImageTk
from Tkinter import Button, Label
import threading
from multiprocessing import Process, Value, Array
window = Tk();
global pct_in_use
global available_mbytes
global utilization
global hours_up
a= 0
b=0
def build_labels(gui, string):
var = StringVar()
label = Label( gui, textvariable=var, relief=RAISED )
var.set(string)
return label
def get_uptime():
global hours_up
c = wmi.WMI()
secs_up = int([uptime.SystemUpTime for uptime in c.Win32_PerfFormattedData_PerfOS_System()][0])
hours_up = secs_up / 3600
return hours_up
def get_cpu():
global utilization
c = wmi.WMI()
utilizations = [cpu.LoadPercentage for cpu in c.Win32_Processor()]
utilization = int(sum(utilizations) / len(utilizations)) # avg all cores/processors
return utilization
def get_mem_mbytes():
global available_mbytes
c = wmi.WMI()
available_mbytes = int([mem.AvailableMBytes for mem in c.Win32_PerfFormattedData_PerfOS_Memory()][0])
return available_mbytes
def get_mem_pct():
global pct_in_use
c = wmi.WMI()
pct_in_use = int([mem.PercentCommittedBytesInUse for mem in c.Win32_PerfFormattedData_PerfOS_Memory()][0])
return pct_in_use
def Draw():
global mem_per_lb
global cpu_lb
global up_time_lb
global mb_used_lb
mem_pct = 0
mem_per_lb = tk.Label(text='Memory % ' + str(mem_pct))
mem_per_lb.place(x=10, y=10)
cpu = 0
cpu_lb = tk.Label(text='CPU % ' + str(cpu))
cpu_lb.place(x=10, y=30)
mem_pct = 0
up_time_lb = tk.Label(text='UP Time % ' + str(mem_pct))
up_time_lb.place(x=10, y=50)
mem_pct = 0
mb_used_lb = tk.Label(text='Memory MB ' + str(mem_pct))
mb_used_lb.place(x=10, y=70)
def Refresher():
global mem_per_lb
global cpu_lb
global up_time_lb
global mb_used_lb
mem_pct = get_mem_pct()
cpu = get_cpu()
up_time = get_uptime()
mbused = get_mem_mbytes()
window.wm_title('Vision' + time.asctime())
mem_per_lb.configure(text='Memory % ' + str(pct_in_use))
cpu_lb.configure(text='CPU ' + str(utilization))
up_time_lb.configure(text='UP Time ' + str(hours_up))
mb_used_lb.configure(text='Memory MB ' + str(available_mbytes))
window.after(200, Refresher) # every second...
def draw_window(): #creates a window
window.geometry('704x528+100+100')
image = Image.open('bg.jpg') #gets image (also changes image size)
image = image.resize((704, 528))
imageFinal = ImageTk.PhotoImage(image)
label = Label(window, image = imageFinal) #creates label for image on window
label.pack()
label.place(x = a, y = b) #sets location of label/image using variables 'a' and 'b'
Draw()
Refresher()
window.mainloop()
up_time_p = Process(target=get_uptime())
cpu_p = Process(target=get_cpu())
mb_p = Process(target=get_mem_mbytes())
pct_p = Process(target=get_mem_pct())
win_p = Process(target=draw_window())
up_time_p.start()
mb_p.start()
pct_p.start()
cpu_p.start()
win_p.start()
up_time_p = Process(target=get_uptime())
cpu_p = Process(target=get_cpu())
mb_p = Process(target=get_mem_mbytes())
pct_p = Process(target=get_mem_pct())
win_p = Process(target=draw_window())
我认为当您为流程提供目标时,您不应该包含括号。如果这样做,函数将在主线程中执行,无论这些函数返回什么,都将成为目标。
up_time_p = Process(target=get_uptime)
cpu_p = Process(target=get_cpu)
mb_p = Process(target=get_mem_mbytes)
pct_p = Process(target=get_mem_pct)
win_p = Process(target=draw_window)
根据 Kevin的回答,您在创建每个流程实例时调用函数。所以它们实际上都在主进程中运行。
但是,一旦解决了这个问题,您的"全局"变量就不会按预期工作。创建进程时,它会占用父进程内存的副本。对该内存的任何更改都不会在进程之间共享。
为了达到你想要的结果,你必须使用Python的线程库。不是多进程库。
线程与父进程共享相同的内存空间。这可能会导致自己的问题。虽然在您的情况下,您要更改的全局变量只是整数常量,所以应该没问题。
from threading import Thread
data_funcs = (
get_uptime,
get_cpu,
get_mem_mbytes,
get_mem_pct,
draw_window
)
threads = [Thread(target=f) for f in data_funcs]
for t in threads:
t.start()
是您应该使用的一般模式。然后,您必须找出一种在关闭主进程时杀死这些线程的方法,否则它将挂起。