views:

111

answers:

5

using code from this site: http://www.saltycrane.com/blog/2008/09/simplistic-python-thread-example/

The code is

import time
from threading import Thread

def myfunc(i):
    print "sleeping 5 sec from thread %d" % i
    time.sleep(5)
    print "finished sleeping from thread %d" % i

for i in range(10):
    t = Thread(target=myfunc, args=(i,))
    t.start()

and I get this output:

sleeping 5 sec from thread 0
sleeping 5 sec from thread 1
sleeping 5 sec from thread 2
sleeping 5 sec from thread 3
sleeping 5 sec from thread 4
sleeping 5 sec from thread 5
sleeping 5 sec from thread 6
sleeping 5 sec from thread 7
sleeping 5 sec from thread 8
sleeping 5 sec from thread 9
finished sleeping from thread 0
finished sleeping from thread 2
finished sleeping from thread 4
finished sleeping from thread 1finished sleeping from thread 6finished sleeping from   thread 8
finished sleeping from thread 5finished sleeping from thread 7finished sleeping from thread 9

finished sleeping from thread 3

what going on here? I am ok with the threads not printing in order because this is possible, but why are they not printing on newlines at the end? I am using python 2.6 under windows xp

+2  A: 

I think they when a thread didn't print a new line it's because the control was passed to another thread before the first thread printed the new line.

Rivka
I think you may be right. That must mean the print command only sends a char at a time. There are 10 newline chars because I checked... Strange that only the newline chars were being shifted. must just be the timing.
Richard
It's not printing one character at a time (well, of course, on some level it is); it's just that the behavior of the print statement is composed of two steps: 'print the argument' followed by 'print a newline if the argument wasn't followed by a comma'. The Python thread scheduler can switch threads in between those two steps, but it won't switch in the middle of one - hence the behavior you see.
Russell Borogove
A: 

Because print isn't atomic a thread's print can be interrupted by another thread at any time. If thread1 is half done printing and thread2 interrupts it and starts printing, the output will be interleaved with thread1 and thread2's output.

shookster
+5  A: 

You've just discovered why programming with threads is hard :)

What's happening is that all your threads are getting woken up at almost the same time. One thread starts printing out "finished sleeping from thread 1" and before it gets a chance to print that last "\n", another thread comes and prints "finished sleeping from thread 6", and on and on. Those newlines aren't being skipped, they're just moved around and bunched up elsewhere. That's probably why a line has been skipped before "finished...3". My guess is that there are many trailing blank lines that got removed due to formatting.

Use threading.Lock to put synchronization around your print statements so that multiple prints can't happen at the same time.

Karmastan
A: 

Indeed it's not thread safe to print. In your example you might want to use the logging module. Or you could create a thread safe print.

DiggyF
+4  A: 

print implemented by multiple opcodes, specifically the newline is a seperate one. Python will context switch between opcodes:

>>> def f(o):
...     print o
...     
...     

>>> from dis import dis

>>> dis(f)
  2           0 LOAD_FAST                0 (o)
              3 PRINT_ITEM          
              4 PRINT_NEWLINE       
              5 LOAD_CONST               0 (None)
              8 RETURN_VALUE        
Alex Gaynor