2014-12-22 70 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