- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
通过下面的代码,我尝试使用 ThreadPoolExecutor
在 jupyter-notebook 上并行打印一堆东西。请注意,使用函数 show()
时,输出不是您通常所期望的。
from concurrent.futures import ThreadPoolExecutor
import sys
items = ['A','B','C','D','E','F',
'G','H','I','J','K','L',
'M','N','O','P','Q','R',
'S','T','U','V','W','X','Y','Z']
def show(name):
print(name, end=' ')
with ThreadPoolExecutor(10) as executor:
executor.map(show, items)
# This outputs
# AB C D E F G H I J KLMNOP QR STU VW XY Z
但是当我尝试使用 sys.stdout.write()
时,我没有得到这种行为。
def show2(name):
sys.stdout.write(name + ' ')
with ThreadPoolExecutor(10) as executor:
executor.map(show2, items)
# This gives
# A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
奇怪的是,我在 jupyter notebook 上以及通过编写 .py 文件并运行它都进行了尝试。但是对于后者,我似乎没有遇到这个问题。我尝试搜索,但我得到的只是 python-3.x 中的 print()
是线程安全的。如果它确实是线程安全的,谁能解释为什么会这样?
最佳答案
实际上不需要指定 end
来公开它;即使只是执行 print(name)
有时也会导致字母彼此相邻:
A
B
C
D
EF
G
H
I
即使 flush=True
也无法修复它。
打印功能在CPython中实现here ,并且是用 C 语言编写的。有趣的是:
for (i = 0; i < nargs; i++) {
if (i > 0) {
if (sep == NULL)
err = PyFile_WriteString(" ", file);
else
err = PyFile_WriteObject(sep, file,
Py_PRINT_RAW);
if (err)
return NULL;
}
err = PyFile_WriteObject(args[i], file, Py_PRINT_RAW);
if (err)
return NULL;
}
if (end == NULL)
err = PyFile_WriteString("\n", file);
else
err = PyFile_WriteObject(end, file, Py_PRINT_RAW);
您可以看到它为每个参数调用一次 PyFile_WriteObject
(如果指定,则为 sep
),然后为 end
再调用一次> 参数(PyFile_WriteString
基本上只是 PyFile_WriteObject
的包装器,它采用 const char*
而不是 PyObject
) – 我假设最终有机会在这些调用之间的某处进行上下文切换。
每次调用 PyFile_WriteString
本质上与调用(在 Python 中)sys.stdout.write
相同,这可以解释为什么在执行 sys.stdout.write(name + ' ')
;如果您改为这样做:
sys.stdout.write(name)
sys.stdout.write(" ")
这更像是 print 函数本身所做的事情,这也解释了为什么 print(name + "", end="")
也能工作。
关于python - print() 中的结束 ='...' 键不是线程安全的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50551637/
我是一名优秀的程序员,十分优秀!