Python GUI多处理并且仍然冻结

时间:2014-12-22 20:49:06

标签: python multithreading python-2.7 multiprocessing

我使用TKinter为即时制作的python程序绘制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()

2 个答案:

答案 0 :(得分:2)

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)

答案 1 :(得分:1)

根据Kevin的回答,您在创建每个流程实例时调用这些函数。所以他们实际上都在主要流程中运行。

但是,一旦解决了这个问题,您的“全局”变量就无法按预期运行。创建进程时,它会占用父进程内存的COPY。对进程之间不共享对该内存的任何更改。

要实现您希望的结果,您必须使用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()

您应该使用的一般模式。然后,当您关闭主进程或者它将挂起时,您必须找出杀死这些线程的方法。