python3的print是线程安全的

2019年12月27日 / 296次阅读 / Last Modified 2020年5月23日
print多线程

在多线程的场景下,使用print输出,心中总是有个疑惑,多线程切换时,是否会导致打印输出混乱?搜索了一番后,这个问题有了结论,python2的print是线程不安全的,多线程打印输出会造成混乱;而python3的print是线程安全的,多线程打印输出不会造成混乱!

2020年python基金会就不再维护python2了,其print的线程不安全,我就不纠结了。

我们可以写一个python3多线程的测试程序,来观察print的输出是否会混乱。下面是我自己写的一段代码:

import time
import threading

def a():
    time.sleep(0.1)
    print('hello 12345')

ts = []
for i in range(100):
    t = threading.Thread(target=a)
    t.start()

反复测试了好几遍,没有观察到打印混乱的情况出现。

另一个方法是反汇编看看python3的print函数:

>>> def a():
...     print('hello')
...
>>> dis.dis(a)
  2           0 LOAD_GLOBAL              0 (print)
              2 LOAD_CONST               1 ('hello')
              4 CALL_FUNCTION            1
              6 POP_TOP
              8 LOAD_CONST               0 (None)
             10 RETURN_VALUE

CALL_FUNCTION就是调用print,这是一句python3虚拟机的opcode,因此是原子操作,因此print是线程安全的!

在python2中,可以使用sys.stdout.write来代替print,实现线程安全的原子打印输出。我们在python3中看看sys.stdout.write的反汇编情况:

>>> def b():
...     import sys
...     sys.stdout.write('hello')
...
>>> dis.dis(b)
  2           0 LOAD_CONST               1 (0)
              2 LOAD_CONST               0 (None)
              4 IMPORT_NAME              0 (sys)
              6 STORE_FAST               0 (sys)

  3           8 LOAD_FAST                0 (sys)
             10 LOAD_ATTR                1 (stdout)
             12 LOAD_METHOD              2 (write)
             14 LOAD_CONST               2 ('hello')
             16 CALL_METHOD              1
             18 POP_TOP
             20 LOAD_CONST               0 (None)
             22 RETURN_VALUE

16 CALL_METHOD对应的就是调用sys.stdout.write函数,也是一行python汇编,也是原子的。

因此,在python3中,我们可以放心大胆的使用print函数,在多线程环境下打印输出。

-- EOF --

本文链接:https://www.pynote.net/archives/1641

留言区

《python3的print是线程安全的》有2条留言

电子邮件地址不会被公开。 必填项已用*标注

  • 麦新杰

    还有Queue模块,也线程安全。 [回复]

  • 麦新杰

    python的logging模块也是线程安全的。 [回复]


前一篇:
后一篇:

More


©Copyright 麦新杰 Since 2019 Python笔记

go to top