2014-12-22 71 views
1

我正在使用TKinter为一个Python程序即时制作一个图形用户界面,我有它在200毫秒左右更新,但当程序查询数据锁定程序,因为它需要一秒获取数据。我试图将它写入多处理,所以每个查询都将是它自己的进程,并且只与全局变量共享信息,因为我的程序是一个使用wmi获取性能数据的实时程序。至少这是我迄今为止。刚开始时不是最终目标。所以如果你能帮我弄清楚,为什么即使在多处理的情况下,如果我在屏幕上拖动应用时查询信息,它也会冻结一秒钟。Python GUI多处理和仍然冻结

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() 

回答

1

根据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() 

是您应该使用的一般模式。那么当你关闭主进程或者它会挂起时,你必须找出一种杀死这些线程的方法。

+0

实际上,通过代码阅读还有其他这些线程如何工作的问题,这些线程只会运行一次并退出,因为它们不包含任何循环,您必须在刷新器内创建并运行这些线程。 – aychedee

1
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) 
+0

我认为这绝对是当前问题的解决方案,但下一个问题将是这些'全局'变量不会跨进程全局... – aychedee