我应该使用事件,信号量,锁,条件或其组合来管理安全退出我的多线程Python程序吗?

时间:2018-06-06 23:53:52

标签: python multithreading python-3.x python-multithreading

我正在编写一个多线程的python程序,其中主线程和它生成的其他线程作为守护进程运行(但不是Thread.daemon = True),它们查找某些目录中的某些文件并在它们存在时对它们执行操作。可能在一个/任何线程中发生错误,这将导致整个程序退出。但是,我需要其他线程在退出之前完成当前的工作。

根据我的理解,如果我为生成的线程设置myThread.daemon = True,它们将在主线程退出时立即自动退出。但是,我希望其他线程在退出之前完成当前的工作(除非错误是某种灾难性的失败,在这种情况下,我可能只是安全地退出所有内容,安全与否)。因此,我没有为线程将守护进程属性设置为True。

查看线程模块文档以及我可用的各种对象,例如事件,信号量,条件和锁,我不确定处理我的情况的最佳方法。另外,当程序因SIGTERM / SIGINT信号需要终止时,我不确定如何处理这种情况。

一些代码说明了我的程序结构的简化版本:

import threading
import signals
import glob
import time

class MyThread1( threading.thread ):
    def __init__( self, name='MyThread1' ):
        threading.Thread.__init__( self )
        self.name = name
        return
    def run( self ):
        while True:
            filePathList = glob.glob( thisThreadDir + '/*.txt' )
            for file in filePathList:
                try:
                    doSomeProcessing( file )
                    # Then move the file to another thread's dir
                    # or potentially create a new file that will 
                    # be picked up by another thread
                except:
                    # Need to potentially tell all other threads
                    # to finish task and exit depending on error

            # I assume this would be the place to check for some kind of
            # flag or other indication to terminate the thread?
            time.sleep( 30 )


# Now imagine a few more custom threads with the same basic structure, 
# except that what is happening in doSomeProcessing() will obviously vary

# Main Thread/Script
def sigintHandler( SIGINT, frame ):
    # How do I handle telling all threads to finish their current loop
    # and then exit safely when I encounter this signal?
    sys.exit( 1 )

def sigtermHandler( SIGTERM, frame ):
    # Same question for this signal handler
    sys.exit( 1 )

signal.signal( signal.SIGINT, sigintHandler )
signal.signal( signal.SIGTERM, sigtermHandler )

myOtherThread1 = MyThread1()
myOtherThreadN = MyThreadN()

myOtherThread1.start()
myOtherThreadN.start()

while True:
    filePathList = glob.glob( mainDir + '/*.txt' )
    for file in filePathList:
        try:
            doMainProcessing( file )
            # Move file or write a new one in another thread's dir
        except:
            # Again, potentially need to exit the whole program, but want 
            # the other threads to finish their current loop first 

    # Check if another thread told us we need to exit?
    time.sleep( 30 )

1 个答案:

答案 0 :(得分:2)

我会使用elasticache 向线程发出信号,告知它应退出

  • Event
  • 中创建活动
  • __init__中的wait()用于run(),并查看何时退出
  • 从外部设置事件以停止线程

要处理线程中的异常,我会对其所做的一切进行sleep / try阻止。捕获某些内容时,存储异常(和/或您需要的任何其他信息),清理并退出该线程。

外部,在主线程中,检查所有线程中的存储异常,如果发现任何异常,则向所有线程发出信号,告知它们应该退出。

要处理主线程中的异常(还包括except),请在此处设置SIGINT / try块,并向所有线程发出信号以停止

所有这些,虚拟异常和调试打印:

except