Python:多线程复制-线程仍然处于活动状态
你好,我的问题是我有一个多线程复制类。复制工作正常,但程序不会退出,因为复制后线程仍处于活动状态。我试图构建一个线程事件,但没有效果。t.join()永远不会结束,因为线程是活动的。我还将它们设为daemonic,但这是不需要的,因为程序结束了,但当程序停止时线程仍然是活动的。有人知道这里出了什么问题吗?该类的输入是一个数据帧,文件源位于第一列,文件目标位于另一列Python:多线程复制-线程仍然处于活动状态,python,multithreading,multiprocessing,python-multithreading,Python,Multithreading,Multiprocessing,Python Multithreading,你好,我的问题是我有一个多线程复制类。复制工作正常,但程序不会退出,因为复制后线程仍处于活动状态。我试图构建一个线程事件,但没有效果。t.join()永远不会结束,因为线程是活动的。我还将它们设为daemonic,但这是不需要的,因为程序结束了,但当程序停止时线程仍然是活动的。有人知道这里出了什么问题吗?该类的输入是一个数据帧,文件源位于第一列,文件目标位于另一列 import shutil as sh from multiprocessing import Queue, Process, Va
import shutil as sh
from multiprocessing import Queue, Process, Value, Lock, cpu_count
import threading, os, time,queue
class ThreadedCopy():
totalFiles = 0
copyCount = 0
lock = threading.Lock()
def __init__(self,srcDst):
#fileList = srcDst['srcCol']
self.fileQueue = queue.Queue()
self.totalFiles = srcDst.shape[0]
print(str(self.totalFiles) + " files to copy.")
self.threadWorkerCopy(srcDst)
def CopyWorker(self):
while True:
#while True:
fileRow = self.fileQueue.get()
sh.copyfile(fileRow[1], fileRow[2])
self.fileQueue.task_done()
with self.lock:
self.copyCount += 1
percent = (self.copyCount * 100) / self.totalFiles
if (percent%10==0):
print(str(percent) + " percent copied.")
def threadWorkerCopy(self, srcDst):
threads=[]
for fileRow in srcDst.itertuples():
self.fileQueue.put(fileRow)
for i in range(cpu_count()):
t = threading.Thread(target=self.CopyWorker,name='CopyThread')
t.daemon = True
t.start()
#threads.append(t)
self.fileQueue.join()
ThreadedCopy(scrDstDf)
编辑
如果我按“中断”键,程序将挂起:
<ipython-input-14-8d9a9b84e73f> in threadWorkerCopy(self, srcDst)
380 self.stop_event.set()
381 for thread in threads:
--> 382 thread.join()
383
384 #ThreadedCopy(scrDstDf)
/usr/lib/python3.5/threading.py in join(self, timeout)
1052
1053 if timeout is None:
-> 1054 self._wait_for_tstate_lock()
1055 else:
1056 # the behavior of a negative timeout isn't documented, but
/usr/lib/python3.5/threading.py in _wait_for_tstate_lock(self, block, timeout)
1068 if lock is None: # already determined that the C code is done
1069 assert self._is_stopped
-> 1070 elif lock.acquire(block, timeout):
1071 lock.release()
1072 self._stop()
KeyboardInterrupt:
threadWorkerCopy中的(self,srcDst)
380自停止事件集()
381对于螺纹中的螺纹:
-->382 thread.join()
383
384#螺纹副本(scrDstDf)
/连接中的usr/lib/python3.5/threading.py(self,超时)
1052
1053如果超时为无:
->1054自我。等待状态锁定()
1055其他:
1056#没有记录负超时的行为,但是
/usr/lib/python3.5/threading.py in_wait_for_tstate_lock(self、block、timeout)
1068如果lock为None:#已确定C代码已完成
1069断言自我。已停止
->1070 elif锁定获取(块,超时):
1071锁。释放()
1072自动停止()
键盘中断:
您的工作线程在self.fileQueue.get()上被阻塞,这就是它不检查停止事件的原因
解决这个问题最简单的方法是使线程成为守护进程线程。这样,当主线程终止时,它们将自动终止
如果出于某种原因您不想/不能这样做,那么您需要通过在队列中插入一个特殊的标记值来唤醒工作线程,您的工作线程将检查该值,如果工作线程从队列中看到该值,它将自行终止。我也尝试将其设为守护线程,然后程序被找到,但是如果我用“import threading.active_count()”检查活动线程,则这些线程仍然是活动的。如果我一次又一次地执行脚本,那么就会有许多活动线程。@Varlor:这肯定不是由于守护进程线程造成的。请注意,threading.active\u count()
仅统计当前进程上的线程数,因此即使该线程以某种方式生存,它也不会被threading.active\u count()
统计。这些线程是在程序的当前实例中启动的。@Varlor另外,我注意到您使用的是IPython,请注意IPython启动了许多后台线程供其内部使用。我想这些线程可能就是你在这里看到的。也许你是对的,但这意味着每次我执行Ipython脚本时,活动计数都会叠加。但如果我执行一个简单的打印函数,计数不会上升。我还检查了是否是我在代码的另一部分中生成的8个进程,但我认为不是。因为当我在代码中不创建ThreadedCopy()时,线程数不会增加。所以我的问题是,你会如何使用这个特殊的标记?致以最良好的祝愿!:)为什么不让守护进程线程来清理呢?看起来你只是让事情变得更复杂了。