【问题标题】:Python daemon thread does not exit when parent thread exits父线程退出时Python守护线程不退出
【发布时间】:2014-03-17 14:59:39
【问题描述】:

我有一些创建恶魔线程的 Python 代码。父线程几乎立即结束,但守护线程保持打印睡眠。

import threading
import time
def int_sleep():
    for _ in range(1, 600):
        time.sleep(1)
        print("sleep")

def main():
    thread = threading.Thread(target=int_sleep)
    thread.daemon = True
    thread.start()
    time.sleep(2)
    print("main thread end...")

thread = threading.Thread(target=main)
thread.start()

系统版本:

'3.3.3 (v3.3.3:c3896275c0f6, Nov 18 2013, 21:19:30) [MSC v.1600 64 bit (AMD64)]'

打印:

sleep

main thread end...

sleep

sleep

sleep

为什么父线程退出时Python守护线程不退出?

【问题讨论】:

标签: python multithreading daemon


【解决方案1】:

如果你为你的python线程指定thread.daemon = True,那么当只剩下守护进程时程序将立即停止。发送到标准输出的命令丢失。

将此添加到名为 main.py 的文件中

import threading
import time

def int_sleep():
  for _ in range(1, 600):
    time.sleep(1)
    print("sleep")

def main():
  thread = threading.Thread(target=int_sleep)
  thread.daemon = True
  thread.start()
  time.sleep(2)
  print("main thread end...")

thread = threading.Thread(target=main)
thread.daemon = True
thread.start()

像这样运行它:

el@apollo:~/code/python/run01$ python --version
Python 2.7.6
el@apollo:~$ python main.py 
el@apollo:~$

看到它没有打印任何内容,因为线程已启动。您将其设置为守护进程并启动它。然后节目结束了。

额外说明:如果将此代码粘贴到 python 解释器中,所有打印语句都将显示在终端上,因为守护程序永远不会失去与 stdout 的连接。

阅读更多:http://docs.python.org/2/library/threading.html

【讨论】:

  • 为什么我们还要将主线程设置为守护进程?如果我实现这样的脚本......并且如果有一个线程卡在执行中,所有线程(在我们的例子中是守护线程)会在 2 秒的睡眠计时器后终止
  • 是因为你粘贴到终端,而不是作为程序,我上面解释了这个现象。
  • 此答案中提供的额外代码具有误导性,对原始问题的真正答案是在 Python 解释器中运行会产生非退出行为,而作为脚本运行会产生预期行为。
【解决方案2】:

我只能重现 OP 描述的行为('sleep' 的无休止输出)if 从 python shell 完成。如果从文件运行,它会按预期工作(几行 'sleep' 和一行 'main thread end ...' )

同样,如果作为文件运行,第二个程序会立即退出,但在从 python shell 运行时也会打印无休止的“睡眠”语句。

我的结论:由于作为 python shell 的线程即使在“main”完成后继续运行,防止守护程序在从 python shell 运行时被终止。

这可以被认为是一个错误(即 Python 的行为因脚本的运行方式而异)还是预期的?我听从更有经验的 Pythonistas...

顺便说一句 - 使用 Python 3.2.3 测试

【讨论】:

    【解决方案3】:

    为了完整起见,请查看这篇文章。 https://joeshaw.org/2009/02/24/605/

    监控是在一个守护线程内完成的。 Python 文档说 仅:

    A thread can be flagged as a “daemon thread”. The significance
    of this flag is that the entire Python program exits when only
    daemon threads are left.
    

    这听起来不错,对吧?这个话题只是偶尔 抓取一些数据,我们不需要做任何特别的事情 程序关闭。是的,我记得我曾经相信的事情 也是。

    尽管有一个全局解释器锁阻止了 Python 无论如何,真正并发,很有可能 在 Python 运行时启动后,守护线程仍然可以执行 它自己的拆卸过程。这一过程的一个步骤似乎是 将 globals() 中的值设置为 None,这意味着任何模块 解决方法导致 AttributeError 尝试取消引用 无类型。对此的其他变体会导致抛出 TypeError。

    我不确定这是一个已修复的错误,还是仍然存在的错误或按照设计的行为。但是,如果您发现奇怪之处,请记住这一点。

    因此,另一种方法是在子线程中循环退出标志,您可以在完成后在主线程中设置该退出标志。然后在主线程中等待子线程死亡,然后清理。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多