Tal*_*rda 7 python stdout atomic multiprocessing output
我在一些消息来源中读到,print命令不是线程安全的,而且解决方法是使用sys.stdout.write命令,但它仍然不适用于我,并且写入STDOUT不是原子的.
这是一个简短的例子(称为此文件parallelExperiment.py):
import os
import sys
from multiprocessing import Pool
def output(msg):
msg = '%s%s' % (msg, os.linesep)
sys.stdout.write(msg)
def func(input):
output(u'pid:%d got input \"%s\"' % (os.getpid(), str(input)))
def executeFunctionInParallel(funcName, inputsList, maxParallelism):
output(u'Executing function %s on input of size %d with maximum parallelism of %d' % (
funcName.__name__, len(inputsList), maxParallelism))
parallelismPool = Pool(processes=maxParallelism)
executeBooleanResultsList = parallelismPool.map(funcName, inputsList)
parallelismPool.close()
output(u'Function %s executed on input of size %d with maximum parallelism of %d' % (
funcName.__name__, len(inputsList), maxParallelism))
# if all parallel executions executed well - the boolean results list should all be True
return all(executeBooleanResultsList)
if __name__ == "__main__":
inputsList=[str(i) for i in range(20)]
executeFunctionInParallel(func, inputsList, 4)
Run Code Online (Sandbox Code Playgroud)
看看输出:
一世.调用python parallelExperiment.py的输出(注意单词"pid"在某些行中搞砸了):
Executing function func on input of size 20 with maximum parallelism of 4
ppid:2240 got input "0"
id:4960 got input "2"
pid:4716 got input "4"
pid:4324 got input "6"
ppid:2240 got input "1"
id:4960 got input "3"
pid:4716 got input "5"
pid:4324 got input "7"
ppid:4960 got input "8"
id:2240 got input "10"
pid:4716 got input "12"
pid:4324 got input "14"
ppid:4960 got input "9"
id:2240 got input "11"
pid:4716 got input "13"
pid:4324 got input "15"
ppid:4960 got input "16"
id:2240 got input "18"
ppid:2240 got input "19"
id:4960 got input "17"
Function func executed on input of size 20 with maximum parallelism of 4
Run Code Online (Sandbox Code Playgroud)
II.输出调用python parallelExperiment.py> parallelExperiment.log,意思是将stdout重定向到parallelExperiment.log文件(注意行的顺序不好,因为在调用executeFunctionInParallel之前和之后并行调用func,一条消息应该打印):
pid:3244 got input "4"
pid:3244 got input "5"
pid:3244 got input "12"
pid:3244 got input "13"
pid:240 got input "0"
pid:240 got input "1"
pid:240 got input "8"
pid:240 got input "9"
pid:240 got input "16"
pid:240 got input "17"
pid:1268 got input "2"
pid:1268 got input "3"
pid:1268 got input "10"
pid:1268 got input "11"
pid:1268 got input "18"
pid:1268 got input "19"
pid:3332 got input "6"
pid:3332 got input "7"
pid:3332 got input "14"
pid:3332 got input "15"
Executing function func on input of size 20 with maximum parallelism of 4
Function func executed on input of size 20 with maximum parallelism of 4
Run Code Online (Sandbox Code Playgroud)
这是因为multiprocessing.Pool实际使用子进程而不是线程.您需要在进程之间使用显式同步.请注意,链接上的示例,它解决了您的问题.
import os
import sys
from multiprocessing import Pool, Lock
lock = Lock()
def output(msg):
msg = '%s%s' % (msg, os.linesep)
with lock:
sys.stdout.write(msg)
def func(input):
output(u'pid:%d got input \"%s\"' % (os.getpid(), str(input)))
def executeFunctionInParallel(funcName, inputsList, maxParallelism):
output(u'Executing function %s on input of size %d with maximum parallelism of %d' % (
funcName.__name__, len(inputsList), maxParallelism))
parallelismPool = Pool(processes=maxParallelism)
executeBooleanResultsList = parallelismPool.map(funcName, inputsList)
parallelismPool.close()
parallelismPool.join()
output(u'Function %s executed on input of size %d with maximum parallelism of %d' % (
funcName.__name__, len(inputsList), maxParallelism))
# if all parallel executions executed well - the boolean results list should all be True
return all(executeBooleanResultsList)
if __name__ == "__main__":
inputsList=[str(i) for i in range(20)]
executeFunctionInParallel(func, inputsList, 4)
Run Code Online (Sandbox Code Playgroud)