我有下面的代码,它产生10个线程,从文件列表中复制文件。我一次又一次地调用这个文件的不同列表,我发现线程似乎并没有死在一旦fileQueue用完了......我注意到,代码似乎放慢了长操作,然后我在线程内发生崩溃,并开始看到“Thread Thread-45中的异常:”!python线程不会死
这里是我的代码,从我知道一切都在阅读说明书,这是非常干净和简单:
import Queue, threading
from PyQt4 import QtCore, QtGui
import shutil
fileQueue = Queue.Queue()
class ThreadedCopy:
totalFiles = 0
copyCount = 0
lock = threading.Lock()
def __init__(self, inputList, progressBar=False):
self.totalFiles = len(inputList)
print str(self.totalFiles) + " files to copy."
if progressBar:
progressBar = QtGui.QProgressDialog("Copying files...", "Cancel", 0, self.totalFiles)
progressBar.setMinimumDuration(0)
progressBar.setWindowModality(QtCore.Qt.WindowModal)
self.threadWorkerCopy(inputList, progressBar)
else:
self.threadWorkerCopy(inputList)
def CopyWorker(self, progressBar):
while True:
fileName = fileQueue.get()
shutil.copy(fileName[0], fileName[1])
fileQueue.task_done()
with self.lock:
self.copyCount += 1
if not progressBar:
print str(self.copyCount) + "of" + str(self.totalFiles)
percent = (self.copyCount * 100)/self.totalFiles
print "File copy: " + str(percent) + "%"
else:
progressBar.setValue(self.copyCount)
def threadWorkerCopy(self, fileNameList, progressBar=False):
threadCount = 10
for i in range(threadCount):
t = threading.Thread(target=self.CopyWorker, args=(progressBar,))
t.daemon = True
t.start()
for fileName in fileNameList:
fileQueue.put(fileName)
fileQueue.join()
有谁知道为什么线程不只是干净的代码的调用之间死于?从我明白的一旦fileQueue用完,然后他们应该安静地死!
编辑:这里是固定的代码
import Queue, threading
from PyQt4 import QtCore, QtGui
import shutil
fileQueue = Queue.Queue()
class ThreadedCopy:
totalFiles = 0
copyCount = 0
lock = threading.Lock()
def __init__(self, inputList, progressBar=False):
self.totalFiles = len(inputList)
print str(self.totalFiles) + " files to copy."
if progressBar:
progressBar = QtGui.QProgressDialog("Copying files...", "Cancel", 0, self.totalFiles)
progressBar.setMinimumDuration(0)
progressBar.setWindowModality(QtCore.Qt.WindowModal)
self.threadWorkerCopy(inputList, progressBar)
else:
self.threadWorkerCopy(inputList)
def CopyWorker(self, progressBar):
while True:
fileName = fileQueue.get()
if fileName is None:
fileQueue.task_done()
break
shutil.copy(fileName[0], fileName[1])
fileQueue.task_done()
with self.lock:
self.copyCount += 1
if not progressBar:
percent = (self.copyCount * 100)/self.totalFiles
print "File copy: " + str(percent) + "%"
else:
progressBar.setValue(self.copyCount)
def threadWorkerCopy(self, fileNameList, progressBar=False):
threads = []
threadCount = 10
for fileName in fileNameList:
fileQueue.put(fileName)
for i in range(threadCount):
t = threading.Thread(target=self.CopyWorker, args=(progressBar,))
t.daemon = True
t.start()
threads.append(t)
fileQueue.put(None)
for t in threads:
t.join()
谢谢,这非常有帮助!我对while循环没有关闭有同样的想法,但是我认为这不是问题,因为我从文档[doc](https://docs.python.org/2/library/queue.html )。我用我的固定代码更新了我的问题。 – Spencer
链接的示例代码可以很好地作为完成排队任务完成后立即退出的完整脚本。但是对于长时间运行的程序中的函数来说这是一个非常糟糕的方法。这种设计会“泄漏”线程,但是在一段短暂的脚本中是可以的,因为当解释器退出时(线程被设置为守护进程以防止解释器关闭),它们将被清理干净。在您的固定代码中,您可以放弃't.daemon = True'行和'task_done'调用,因为您不再'加入'队列。 – Blckknght
我明白了,没有理由让它们成为守护神,在这一点上,task_done只是多余的。我以为我出于某种原因仍然需要它,但是我发现它仅适用于queue.join函数。谢谢! – Spencer