Time.sleep seems to be blocking main thread, not just child thread?

Viewed 6828

I'm running the following code:

from threading import Thread
from time import sleep

def file_write(file_input, num_lines):
    sleep(10)
    file = open("testfile.txt", "w")
    for line in num_lines:
        file.write("{}: {}".format(line, file_input))

    file.close()


if __name__ == '__main__':
    curr_thread = Thread(target=file_write, args=("Norah", range(5)))
    curr_thread.daemon = False
    curr_thread.start()

The expectation is the main thread will exit immediately, because I don't call join. But it doesn't. Do sleep calls block the main thread too?

EDIT: There is a similar question asked in this thread: time.sleep -- sleeps thread or process? but it's not the same.
I looked at the thread: it says that sleep doesn't cause child processes to block each other, but it doesn't say what happens to the main thread. When I ran the code from the accepted answer, the main thread did not exit immediately, as I thought it would.

UPDATE: Looks like multithreading won't solve my problem: the aim is to run a bunch of tasks in the background. I'm using the subprocess module instead now.

2 Answers

Sleep calls only block the thread in which they're called. Printing anything in the main thread immediately after the call to curr_thread.start() will prove this to you.

However, if you interrupt your code (Ctrl-C), you'll see a useful stack trace. The last call is inside the threading module's _shutdown() method, which appears to be waiting for all non-daemon threads to finish.

t = _pickSomeNonDaemonThread()
while t:
    t.join()
    t = _pickSomeNonDaemonThread()

And reading the documentation for the threading module, you can see that: "The entire Python program exits when no alive non-daemon threads are left." So, because you've done curr_thread.daemon = False, you're forcing the main thread to wait for this thread to finish first.

I should point out, though, that threads inherit the "daemon-ness" of their parents. Since the main thread is never a daemon thread, you could have left off the curr_thread.daemon = False, and you'd get the same behavior.

Of course a sleep in a thread does not block the main thread.

This code demonstrates that main continues:

from threading import Thread
from time import sleep

def file_write(file_input, num_lines):
    print('a')
    sleep(5)
    print('b')


if __name__ == '__main__':
    curr_thread = Thread(target=file_write, args=("Norah", range(5)))
    curr_thread.daemon = False
    curr_thread.start()
    for i in range(5):
        sleep(1)
        print(i)

Output:

a
0
1
2
3
b
4
Related