Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/363.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python:多线程复制-线程仍然处于活动状态_Python_Multithreading_Multiprocessing_Python Multithreading - Fatal编程技术网

Python:多线程复制-线程仍然处于活动状态

Python:多线程复制-线程仍然处于活动状态,python,multithreading,multiprocessing,python-multithreading,Python,Multithreading,Multiprocessing,Python Multithreading,你好,我的问题是我有一个多线程复制类。复制工作正常,但程序不会退出,因为复制后线程仍处于活动状态。我试图构建一个线程事件,但没有效果。t.join()永远不会结束,因为线程是活动的。我还将它们设为daemonic,但这是不需要的,因为程序结束了,但当程序停止时线程仍然是活动的。有人知道这里出了什么问题吗?该类的输入是一个数据帧,文件源位于第一列,文件目标位于另一列 import shutil as sh from multiprocessing import Queue, Process, Va

你好,我的问题是我有一个多线程复制类。复制工作正常,但程序不会退出,因为复制后线程仍处于活动状态。我试图构建一个线程事件,但没有效果。t.join()永远不会结束,因为线程是活动的。我还将它们设为daemonic,但这是不需要的,因为程序结束了,但当程序停止时线程仍然是活动的。有人知道这里出了什么问题吗?该类的输入是一个数据帧,文件源位于第一列,文件目标位于另一列

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()时,线程数不会增加。所以我的问题是,你会如何使用这个特殊的标记?致以最良好的祝愿!:)为什么不让守护进程线程来清理呢?看起来你只是让事情变得更复杂了。