我需要我的程序并行执行某个功能。但是该功能根据用户与程序的交互方式分支到不同的结果。我在名为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)
这是我的代码的简化示例。我的问题是我的代码只执行两个函数中的一个而不是两个。因此,如果我创建了一个称为下载,上传,下载的字典,那么它将执行三次下载,而不是所需的模式。
答案 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()保证是线程安全的。