파일 목록에서 파일을 복사하는 10 개의 스레드를 생성하는 다음 코드가 있습니다. 나는 파일의 다른 목록에 대해 이것을 반복해서 호출하고 있는데, 나는 fileQueue가 종료되면 쓰레드가 죽어가는 것 같지 않다는 것을 알았다. 코드가 오랜 작업으로 느려지는 것처럼 보였다. 스레드 내에서 충돌이 발생하여 "스레드 Thread-45 예외 :"가 표시되기 시작했습니다. 스레드 그냥 깔끔하게 코드의 호출 사이에 죽어없는 이유 파이썬 스레드가 죽지 않는다
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가 없어지면 일단 조용히 죽어야한다는 것을 이해하는 것으로부터!
편집 : 여기 당신은 아마 모든 스레드 .join
전화를 잊었 고정 코드
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' 호출을 버릴 수 있습니다. 왜냐하면 여러분은 더 이상 큐에'join'하지 않기 때문입니다. – Blckknght
나는 이것들을 데몬틱하게 만들 이유가 없으며이 시점에서 task_done은 단지 중복되어있다. 나는 어떤 이유로 든 여전히 필요하다고 생각했지만 queue.join 함수에서만 볼 수 있습니다. 감사! – Spencer