Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What makes Python3's print function thread safe?

I've seen on various mailing lists and forums that people keep mentioning that the print function in Python 3 is thread safe. From my own testing, I see no reason to doubt that.

import threading
import time
import random

def worker(letter):
    print(letter * 50)


threads = [threading.Thread(target=worker, args=(let,)) for let in "ABCDEFGHIJ"]
for t in threads:
    t.start()
for t in threads:
    t.join()

When I run it with Python 3, even though some of the lines may be out of order, they are still always on their own lines. With Python 2, however, the output is fairly sporadic. Some lines are joined together or indented. This is also the case when I from __future__ import print_function

  • Python 2.7 builtin_print <- not thread safe
  • Python 3.6 builtin_print <- thread safe?

I'm just trying to understand WHY this is the case?

like image 222
Goodies Avatar asked Mar 17 '17 22:03

Goodies


People also ask

What makes an object thread-safe?

A MessageService object is effectively immutable since its state can't change after its construction. So, it's thread-safe. Moreover, if MessageService were actually mutable, but multiple threads only have read-only access to it, it's thread-safe as well.

How do you make a function thread-safe?

Making a function threadsafe In multithreaded programs, all functions called by multiple threads must be threadsafe. However, a workaround exists for using thread-unsafe subroutines in multithreaded programs. Non-reentrant functions usually are thread-unsafe, but making them reentrant often makes them threadsafe, too.

Is printing thread-safe?

The print() function is a built-in function for printing a string on stdout and is not thread-safe. The print() function takes a string message, or an object that can be converted to a string.

Is printf () thread-safe?

the standard C printf() and scanf() functions use stdio so they are thread-safe.


1 Answers

For Python 3.7: The print() function is a builtin, it by default sends output to sys.stdout, the documentation of which says, among other things:

When interactive, stdout and stderr streams are line-buffered. Otherwise, they are block-buffered like regular text files. You can override this value with the -u command-line option.

So its really the combination of interactive mode and sys.stderr that is responsible for the behaviour of the print function as demonstrated in the example.

And we can get closer to the truth if the worker function in your example program is changed to

def worker(letter):
    print(letter*25, letter*25, sep='\n')

then we get outputs similar to the one below, which clearly shows that print in itself is not thread safe, what you can expect is that individual lines do not get interleaved with each other.

DDDDDDDDDDDDDDDDDDDDDDDDDJJJJJJJJJJJJJJJJJJJJJJJJJ

JJJJJJJJJJJJJJJJJJJJJJJJJ
DDDDDDDDDDDDDDDDDDDDDDDDDGGGGGGGGGGGGGGGGGGGGGGGGG
GGGGGGGGGGGGGGGGGGGGGGGGGAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAHHHHHHHHHHHHHHHHHHHHHHHHH
HHHHHHHHHHHHHHHHHHHHHHHHH


FFFFFFFFFFFFFFFFFFFFFFFFF
IIIIIIIIIIIIIIIIIIIIIIIIICCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCC
IIIIIIIIIIIIIIIIIIIIIIIII

EEEEEEEEEEEEEEEEEEEEEEEEE

EEEEEEEEEEEEEEEEEEEEEEEEEFFFFFFFFFFFFFFFFFFFFFFFFF

BBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBB

So ultimately thread safety of print is determined by the buffering strategy used.

like image 189
xxa Avatar answered Oct 20 '22 10:10

xxa