2012-06-05 61 views
0

我需要我的程序並行地執行某個函數。但是該功能根據用戶與程序的交互方式分支出不同的結果。我在一個名爲threadGUI.py的模塊中有一個簡單的GUI,它有兩個選項:下載和上傳。這些選項創建包含與該函數相關的變量的字典。這些字典存儲在存儲在thread_test.py模塊中的主字典中。當一個接一個地執行時,這些工作正常,但是當我嘗試並行執行時出現錯誤。在threadGUI.py 穿線相關的代碼:在Python中爲不同的結果執行相同的函數

def OnStartClick(self): 
    for i in thread_test.dictList.values():  #the main dictionary is stored as a global in thread_test.py 
    thread = Thread(target = thread_test.begin_tests, args = (i,)) 
    thread.start() 
    print "thread finished...exiting" 

上述函數調用thread_test.py模塊內的begin_test功能。功能如下:

def begin_tests(arg): 
    print arg 
    print dictList 
    dictItem = arg 
    print dictItem 
    if dictItem['Type'] == "HTTP_Downloading": 
     print "DOWNLOAD" 
    elif dictItem['Type'] == "FTP_Uploading": 
     print "UPLOAD" 
    else: 
     print "Invalid input" 
     sys.exit(1) 

這是我的代碼的簡化示例。我的問題是,我的代碼只執行兩個而不是兩個函數中的一個函數。所以如果我創建了一個名爲下載,上傳,下載的字典,它會執行三次下載,而不是所需的模式。

回答

2

的問題是不是在代碼貼:

from threading import Thread 

dictList = { 
    'foo': { 'Type': 'HTTP_Downloading' }, 
    'bar': { 'Type': 'FTP_Uploading' }, 
    'baz': { 'Type': 'HTTP_Downloading' } 
} 

def begin_tests(arg): 
    print arg 
    print dictList 
    dictItem = arg 
    print dictItem 
    if dictItem['Type'] == "HTTP_Downloading": 
     print "DOWNLOAD" 
    elif dictItem['Type'] == "FTP_Uploading": 
     print "UPLOAD" 
    else: 
     print "Invalid input" 
     sys.exit(1) 

def OnStartClick(self): 
    for i in dictList.values():  #the main dictionary is stored as a global in thread_test.py 
    thread = Thread(target = begin_tests, args = (i,)) 
    thread.start() 
    print "thread finished...exiting" 

OnStartClick(None) 

結果:

{'Type': 'HTTP_Downloading'} 
{'baz': {'Type': 'HTTP_Downloading'}, 'foo': {'Type': 'HTTP_Downloading'}, 'bar': {'Type': 'FTP_Uploading'}} 
{'Type': 'HTTP_Downloading'} 
{DOWNLOAD 
{'Type': 'FTP_Uploading'} 
'Type': 'HTTP_Downloading'} 
{'baz': {'Type': 'HTTP_Downloading'}, 'foo': {'Type': 'HTTP_Downloading'}, 'bar': {'Type': 'FTP_Uploading'}} 
{'baz': {'Type': 'HTTP_Downloading'}, 'foo': {'Type': 'HTTP_Downloading'}, 'bar': {'Type': 'FTP_Uploading'}} 
thread finished...exiting 
{'Type': 'HTTP_Downloading'} 
DOWNLOAD 
{'Type': 'FTP_Uploading'} 
UPLOAD 

在猜測中,要重複使用內部字典。

UPDATE:

我覺得這種情況下是通過使用工人池和隊列策略,較好地解決了。喜歡的東西:

from Queue import Queue 
from threading import Thread 

queue = Queue() # Replaces the dictList 

threads = [] 
for n in range(10): 
    thread = Thread(target = worker, args = (begin_tests, queue,)) 
    thread.start() 
    threads.append(thread) 

Stop = object() 
def worker(work, queue): 
    while True: 
     task = queue.get() 
     if task is Stop: 
      break 
     work(task)    

使用它,像這樣:

queue.put({ 'Type': 'HTTP_Downloading' }) 
queue.put({ 'Type': 'FTP_Uploading' }) 
queue.put({ 'Type': 'HTTP_Downloading' }) 
queue.put(Stop) 

這本身不解決變異的類型的字典的問題;必須在別處修復。這個策略有兩個好處:它保留了任務的順序,並且不會冒失去任務的風險:dict使有限的併發性保證,而Queue()保證是線程安全的。

+0

在發佈我的問題後,我很快意識到這一點,所以您的猜測是正確的。儘管如此,我目前不知道如何去解決問題。一旦下一個線程啓動,它就會覆蓋dictItem並導致以前正在進行的線程中的錯誤。 有什麼辦法可以修復一個全局變量到那個特定的線程而不是影響所有的線程? – Joe

+0

隊列聽起來不錯,但是這個程序現在已經不能切換了。也許如果我有時間來優化代碼,我可以給他們一個去。 事實證明,我太亂了全局變量,我發現本地線程存儲解決了我的問題。無論如何感謝您的幫助,它幫助我縮小了問題的範圍! – Joe

相關問題