2019年12月27日 / 504次阅读 / 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条留言
Ctrl+D 收藏本页
©Copyright 麦新杰 Since 2019 Python笔记
还有Queue模块,也线程安全。 [ ]
python的logging模块也是线程安全的。 [ ]