【问题标题】:Kill a Daemon Thread Whilst the Script is still Running在脚本仍在运行时杀死守护线程
【发布时间】:2012-03-17 06:55:26
【问题描述】:

我的 python 脚本创建了很多线程,它们都是守护线程,我发现我收到一个错误提示“内存不足”。

如何在我的脚本/应用程序运行时终止守护线程?

我了解守护线程的概念,即当我的进程(脚本或应用程序)关闭/完成时它们会自行销毁。但是我想在我的脚本仍在运行时杀死我的一些守护线程以避免“内存不足”错误。

当队列中没有更多任务时,我的下面的线程会自行杀死吗?

class ParsePageThread(threading.Thread):
    THREAD_NUM = 0

    def __init__(self, _queue):
        threading.Thread.__init__(self)
        self.queue       = _queue

    def run(self):
        while(True):
            try:
                url = self.queue.get()
            except Queue.Empty,e:
                return # WILL this kill the thread?
            finally:
                self.queue.task_done()

【问题讨论】:

  • 这听起来像是你做错了事。如果您可能会耗尽所有内存而不是杀死随机内存,那么不启动线程不是更好吗?
  • 您可能会受益于更高的抽象级别,例如ThreadPoolExecutor(重用线程来完成工作,而不是创建新线程)

标签: python multithreading


【解决方案1】:

我会先回答你的第二个问题,因为它更容易。是的,从 run 方法返回确实会停止线程。详细解释是threading: Thread Objectsdoc。

要在自然完成之前停止正在运行的线程,您必须获得更多创意。线程对象上没有直接的 kill 方法。您需要做的是使用共享变量来定义线程的状态。

alive = True

class MyThread(threading.Thread):
    def run():
        while(alive):
            #do work here

在其他一些代码中,当您检测到停止该线程的条件时,其他线程只是将 alive 设置为 False:

alive = False

这是一个简单的例子,我将把它留给你来扩展到多个线程。

危险

这个例子之所以有效,是因为读取和设置布尔变量是 Python 中的 原子 操作,因为全局解释器锁。 Here 是一个很好的底层 Python 线程教程。您应该坚持使用 Queue 对象,因为这正是它的用途。

如果您不只是从多个线程读取和设置简单变量,您应该使用LocksReentrant Locks,具体取决于您的设计和需求。即使是像比较和交换这样简单的操作,也可能在您的程序中导致难以调试的问题。

关于 python 多线程的另一条建议是永远不要在解释器线程中做任何重要的工作。它应该设置并启动所有其他线程,然后休眠或等待condition object,直到程序退出。原因是没有其他 python 线程可以接收操作系统signals。这意味着没有其他线程可以处理 Ctrl+C aka KeyboardInterrupt 异常。让主线程处理KeyboardInterrupt 异常,然后将所有活动变量设置为 False 是一个很好的做法,这样您就可以快速退出程序。这在开发过程中特别有用,因此您不必在犯错时不断杀死东西。

【讨论】:

  • @J.F.Sebastian 这些都是好点,我同意 RLock 不一定更好。它们可以更实用,并使界面设计更简单。这样您就不必为持有或不持有锁指定不同的接口。特别是在 Python 中,由于 GIL,您并没有真正通过使代码成为多线程来获得任何速度。在几乎所有情况下,您实际上都是通过增加锁定开销来使其变慢,所以我尽量避免使用线程。我发现当我必须在 Python 中做多线程时(通常是因为外部库)RLock 更方便。
  • 这是一个非常好的主意,但是,我遇到了一个更有趣的问题......线程有时会在尝试与远程服务器建立 tty 会话时挂起,所以我将无法使用“活动”标志。有没有其他方法可以杀死线程?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-04
  • 2019-05-01
  • 1970-01-01
  • 2011-01-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多