Python主线程何时退出?

4

我正在阅读《Python标准库实例》这本书,但当我翻到第509页时感到有些困惑。

在此之前,示例程序隐式地等待所有线程完成其工作后才退出。有时候程序会生成一个作为守护进程运行的线程,以免阻止主程序退出。

但是,当我运行了一些代码后,得到了相反的结果。代码如下:

    #!/usr/bin/env python
# encoding: utf-8
#
# Copyright (c) 2008 Doug Hellmann All rights reserved.
#
"""Creating and waiting for a thread.
"""
#end_pymotw_header

import threading
import time

def worker():
    """thread worker function"""
    print 'Worker'
    # time.sleep(10000)
    return

threads = []
for i in range(5):
    t = threading.Thread(target=worker)
    threads.append(t)
    t.start()

print "main Exit"

有时候结果会是这样:

Worker
Worker
WorkerWorker

main Exit
Worker

我想问一下,在Python启动几个线程后,主线程何时退出?

5个回答

11

当主线程执行完未在单独线程中启动的脚本代码后,它将退出。

由于 t.start() 将启动线程并返回到主线程,因此主线程将继续执行,直到到达脚本底部然后退出。

由于您以非守护进程模式启动了其他线程,它们将持续运行,直到完成。

如果您想要主线程等待所有线程完成后再退出,您应该显式地将它们 join 到主线程。 join 将导致调用 join 的线程等待被加入的线程结束。

for i in range(5):
    threads[i].join()
print "main Exit"

正如@codesparkle指出的那样,更符合Python编程规范的写法是完全跳过索引变量。

for thread in threads:
    thread.join()
print "main Exit"

@codesparkle,我会更新它。我这样写是为了更接近他已有的代码。 - merlin2011

6
根据线程文档

只有守护线程存在时,整个Python程序才会退出。

这与您提供的引用相符,但措辞上略有不同。当您预期`主线程`退出时,它就已经退出了。请注意,在此时,`工作线程`仍在运行 - 您可以在提供的测试输出中看到这一点。因此,主线程已经完成,但整个进程仍在运行,因为还有其他线程正在运行。
区别在于,如果其中一些工作线程被设为守护线程,则在最后一个非守护线程完成时,它们将被强制终止。如果所有工作线程都是守护线程,则整个进程将结束 - 并且您会很快回到系统shell提示符 - 在打印'main exit'后,任何工作线程再也不可能(尽管由于竞态条件,不太可能)打印任何内容。

我认为关键的一点是,即使主线程退出,程序仍然在运行非守护进程子线程。您可以通过在子线程中使用此表达式进行验证:main_thread().is_alive() - coder.in.me

0
请注意,当您打印main Exit时,Main函数并不会立即退出,而是在此之后才会退出。考虑以下程序:
import threading
import time

def worker():
    """thread worker function"""
    print 'Worker'
    time.sleep(1)
    print 'Done'
    return


class Exiter(object):
    def __init__(self):
        self.a = 5.0
        print 'I am alive'
    def __del__(self):
        print 'I am dying'

exiter = Exiter()

threads = []
for i in range(5):
    t = threading.Thread(target=worker)
    threads.append(t)
    t.start()

print "main Exit"

我创建了一个对象,其唯一目的是在最终化时打印“我正在死亡”。我没有在任何地方显式地删除它,因此它只会在主线程完成时死亡,也就是当Python开始杀死所有东西以将内存返回给操作系统时。

如果您运行此代码,您将看到工作线程在主线程完成后仍在工作,但对象仍然存在。 我正在死亡总是在所有工作线程完成任务后才出现。


0

当您的循环执行完成后,主线程将退出。您的主线程正在启动新的异步线程。这意味着它不会等待新线程完成执行。因此,在您的情况下,主线程将并行启动5个线程并退出。


这是不正确的。主线程继续执行,但不会退出,直到所有子线程完成,正如所记录的那样。 - Davidmh
主线程将退出,但进程不会退出。这是怎么回事? - Abhishek Bansal

0
例如如下所示:
    class ThreadA(Thread):
        def __init__(self, mt):
            Thread.__init__(self)
            self.mt = mt

        def run(self):
            print 'T1: sleeping...'
            time.sleep(4)
            print 'current thread is ', self.isAlive()
            print 'main thread is ', self.mt.isAlive()
            print 'T1: raising...'

if __name__ == '__main__':
    mt = threading.currentThread()
    ta = ThreadA(mt)
    ta.start()
    logging.debug('main end')

> T1: 睡眠中...

(MainThread) 主线程结束

当前线程为 True

主线程为 False

T1: 抛出异常...

你可以看到主线程的活动状态是 false 吗?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接