我正在阅读The Python Standard Library by Example
,当我到达第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中退出?
答案 0 :(得分:9)
只要脚本中的所有代码都没有在单独的线程中启动,主线程就会退出。
由于t.start()
将启动线程然后返回主线程,主线程将继续执行,直到它到达脚本底部然后退出。
由于您以非守护进程模式启动了其他线程,因此它们将继续运行直到完成。
如果您希望主线程在所有线程完成之前不退出,则应将它们显式join
到主线程。 join
将导致调用join
的线程等待加入的线程完成。
for i in range(5):
threads[i].join()
print "main Exit"
正如@codesparkle指出的那样,更多Pythonic的写法就是完全跳过索引变量。
for thread in threads:
thread.join()
print "main Exit"
答案 1 :(得分:5)
当只剩下守护程序线程时,整个Python程序退出
这与你给出的引用一致,但是措辞的细微差别显示了你得到的结果。主要线程'当你期望它退出时退出。请注意, worker 线程此时仍在运行 - 您可以在给出的测试输出中看到这一点。所以,主线程已经完成,但整个过程仍在运行,因为还有其他线程仍在运行。
不同之处在于,如果其中一些工作线程被守护,那么当最后一个非守护程序线程完成时,它们将被强行杀死。如果所有工作人员都是守护程序线程,那么整个过程就会完成 - 并且您将在系统shell提示符后返回 - 很快就会打印出主要退出程序',并且在此之后,任何工人打印都会非常罕见(尽管并非不可能,因为竞争条件)。
答案 2 :(得分:0)
你的主线程将以soos的形式退出,因为for循环完成了它的执行。您的主线程正在启动新的异步线程。这意味着它不会等待,直到新线程完成其执行。所以在你的情况下,主线程将并行启动5个线程并退出。
答案 3 :(得分: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开始杀死所有内容以将内存返回给操作系统时。
如果你运行它,你会看到当主线程完成时,工人正在工作,但对象仍然存在。 I am dying
总是在所有工人完成工作之后出现。
答案 4 :(得分: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:提高......你可以看到主线程的活动状态是假的吗?