简体   繁体   中英

when will main thread exit in python

I am reading The Python Standard Library by Example and get confused when I arrived page 509.

Up to this point, the example programs have implicitly waited to exit until all threads have completed their work. Programs sometimes spawn a thread as a daemon that runs without blocking the main program from exiting.

but after I run some codes, I get result that is opposite. The code is like this:

    #!/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"

and sometime the result is this:

Worker
Worker
WorkerWorker

main Exit
Worker

So I want to ask when will main thread exit in python after it starts several thread?

The main thread will exit whenever it is finished executing all the code in your script that is not started in a separate thread.

Since the t.start() will start the thread and then return to the main thread, the main thread will simply continue to execute until it reaches the bottom of your script and then exit.

Since you started the other threads in a non-daemon mode, they will continue running until they are finished.

If you wanted the main thread to not exit until all the threads have finished, you should explicitly join them to the main thread. The join will cause the thread calling join to wait until the the thread being joined is finished.

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

As @codesparkle pointed out, the more Pythonic way to write this would be to skip the index variable entirely.

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

According to the threading docs :

The entire Python program exits when only daemon threads are left

This agrees with the quote you give, but the slight difference in wording shows the result you get. The 'main thread' exits when you would expect it to. Note that the worker threads keep running at this point - you can see this in the test output you give. So, the main thread has finished, but the whole process is still running because there are other threads still running.

The difference is that if some of those worker threads were daemonised, they would be forcibly killed when the last non-daemon thread finished. If all of the workers were daemon threads, then the entire process would finish - and you would be back at your systems shell prompt - very soon after you print 'main exit', and it would be very rare (though not impossible, owing to race conditions) for any worker to print after that.

Your main thread will exit as soos as for loop completes its execution. Your main thread is starting new asynchronous threads. Which means that it will not wait untill new thread finishes its execution. So in your case main thread will start 5 threads in parallel and exit itself.

Note that Main does not exit when you print main Exit , but after it. Consider this program:

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"

I have created an object whose sole purpose is to print "I am dying" when it is being finalised. I am not deleting it explicitly anywhere, so it will only die when the main thread finishes, that is, when Python starts to kill everything to return memory to the OS.

If you run this you will see that workers are working when the main thread is done, but the objects are still alive. I am dying always comes after all the workers have finished their job.

For example as follow:

    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: sleeping...

(MainThread) main end

current thread is True

main thread is False

T1: raising...

you can see the main thread active state is false?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM