在Python中为不同的结果线程化相同的函数

时间:2012-06-05 13:07:15

标签: python function if-statement module python-multithreading

我需要我的程序并行执行某个功能。但是该功能根据用户与程序的交互方式分支到不同的结果。我在名为threadGUI.py的模块中有一个简单的GUI,它有两个选项:下载和上传。这些选项创建包含与函数相关的变量的字典。这些字典存储在主字典中,该字典存储在thread_test.py模块中。这些在一个接一个地执行时工作正常,但是当我尝试并行执行时出错了。 threadGUI.py中的与线程相关的代码:

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)

这是我的代码的简化示例。我的问题是我的代码只执行两个函数中的一个而不是两个。因此,如果我创建了一个称为下载,上传,下载的字典,那么它将执行三次下载,而不是所需的模式。

1 个答案:

答案 0 :(得分: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

猜测,你正在重复使用内部词典。

更新:

我认为通过使用worker-pool-and queue策略可以更好地解决这种情况。类似的东西:

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()保证是线程安全的。