多处理中“无法加载字形”

Dae*_*Dae 5 python matplotlib multiprocessing pathos

我在使用运行图形保存功能的 pathos 多重处理时遇到了问题。

from pathos.multiprocessing import ProcessingPool as Pool
datasets = Pool().map(model_handler, analysisParams)
Run Code Online (Sandbox Code Playgroud)

哪个抛出

  File ".../lib/python3.6/site-packages/matplotlib/backends/backend_pdf.py", line 2029, in draw_text
    font.set_text(s, 0.0, flags=LOAD_NO_HINTING)
RuntimeError: In set_text: could not load glyph
"""

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "wrapper.py", line 410, in <module>
    datasets = Pool().map(model_handler, analysisParams)
  File ".../lib/python3.6/site-packages/pathos/multiprocessing.py", line 137, in map
    return _pool.map(star(f), zip(*args)) # chunksize
  File ".../lib/python3.6/site-packages/multiprocess/pool.py", line 260, in map
    return self._map_async(func, iterable, mapstar, chunksize).get()
  File ".../lib/python3.6/site-packages/multiprocess/pool.py", line 608, in get
    raise self._value
RuntimeError: In set_text: could not load glyph
"""
Run Code Online (Sandbox Code Playgroud)

我目前的理解是,发生这种情况是因为 glyph 被多个进程同时调用。仅当并行执行数>3时才会发生异常,这与该想法一致。我发现有人的解决方法只是重复调用 savefig 直到命令执行完毕,但并行函数包含大量绘图,我不想将每个绘图都包装在 try 语句中。有谁知道如何在并行绘制图形时避免这种异常?谢谢!!

编辑 每个评论请求的最小示例。

from pathos.multiprocessing import ProcessingPool as Pool

def model_handler(analysisParam):
    import matplotlib
    matplotlib.use('agg')
    import matplotlib.pyplot as plt

    figout = plt.figure(figsize=(1, 1))
    axes = figout.add_subplot(1,1,1)
    axes.scatter(range(1000), range(1000))
    figout.savefig('dummyfig{}.pdf'.format(analysisParam), format='pdf')
    return analysisParam

datasets_serial = []
for j in range(20):
    datasets_serial.append(model_handler(j))

datasets = Pool(20).map(model_handler, range(20))
Run Code Online (Sandbox Code Playgroud)

有趣的是,如果我将 dataset_serial 循环替换为dataset_serial = map(model_handler, range(20)),pathos 并行池执行没有问题,但如果我将串行映射对象转换为列表 ( print(list(dataset_serial))),并行池中的字形异常就会回来。