7

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.

Norah Borus
  • 318
  • 3
  • 8
  • 1
    Possible duplicate of [time.sleep -- sleeps thread or process?](https://stackoverflow.com/questions/92928/time-sleep-sleeps-thread-or-process) – Treyten Carey Sep 21 '17 at 18:17
  • 1
    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. – Norah Borus Sep 21 '17 at 18:26
  • Are you doing `curr_thread.join()`? The main thread should exit immediately. Joining the thread will wait until the thread is finished before quitting. – Treyten Carey Sep 21 '17 at 18:32
  • I am not making any join calls: I'm running only what I have pasted above. – Norah Borus Sep 21 '17 at 18:33
  • I just ran the code [here](https://pastebin.com/97r4T3QF). Try it for yourself. You should see it print "a", "b", "d", "e", (main thread exit), "c". Edit: I ran your code as well, the main thread exits immediately as you expected. – Treyten Carey Sep 21 '17 at 18:36
  • Maybe I don't understand what the main thread exit entails. When I run the code in the link, my expectation is that the program will completely exit when the main thread exits, and then the last printout ("c") will be outputted sometime afterwards. Not that the program will halt execution after printing e, and then print c, and then exit , which is what is happening when I run it. – Norah Borus Sep 21 '17 at 18:48
  • Probably depends on what you're using to run your script. In IDLE, the program exits completely before printing c, as you want. – Treyten Carey Sep 22 '17 at 12:44
  • Yes I'm facing the same issue. Works on the python shell. But in a .py script it the main thread waits – Vinay Sep 30 '19 at 09:27

2 Answers2

2

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.

bnaecker
  • 6,152
  • 1
  • 20
  • 33
  • Thing is, if I set curr_thread.daemon = True, then the program exits immediately, but the child thread seems to be torn down in the process: the file-write calls do not execute. – Norah Borus Sep 21 '17 at 18:52
  • @NorahBorus Yes, the second thread will be terminated. This is because the whole process exits, because there are no non-daemon threads left. The main thread is the only non-daemon thread if you set `curr_thread.daemon = True`, right? So when it finishes (immediately, since you never `join()`), the whole process will exit. – bnaecker Sep 21 '17 at 18:59
  • @NorahBorus This is starting to seem a bit like an XY problem. Why do you want to create a second thread at all? Or is this an exercise to understand the threading module? – bnaecker Sep 21 '17 at 19:02
  • I was trying to use the threading module to run some tasks in the background, but it seems it's not the way to go about it. I'll use the subprocess module instead. Thanks for the clarification. – Norah Borus Sep 24 '17 at 12:24
0

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
quamrana
  • 37,849
  • 12
  • 53
  • 71
  • See bnaeckner's comment and my code example: I specified that the question is about what happens when the main thread is exiting. – Norah Borus Sep 21 '17 at 18:53