使用带有部分和映射的多处理的脚本在 Python > 3 上失败,在 2.7 上工作正常,无法 pickle '_thread.lock'

Script using multiprocessing with partial and map failing on Python > 3, working fine on 2.7, cannot pickle '_thread.lock'

直到今天,我还在 Python 2.7 上使用了以下代码,用 matplotlib 并行创建许多 PNG 图片。今天我尝试将所有内容移动到 Python 3.8,我无法适应的部分涉及使用 multiprocessing.

完成的并行化

我的想法是我有一个脚本需要从一个数据文件的不同时间步生成多个具有相似设置的图像。由于可以对绘图例程进行参数化,因此我在分布在不同任务中的 10 个时间步长的块上执行它以加速该过程。

这是脚本的相关部分,考虑到它的长度,我不会粘贴它。

from multiprocessing import Pool
from functools import partial

def main():
    # arguments to be passed to the plotting functions
    # contain data and information about the plot
    args = dict(m=m, x=x, y=y, ax=ax,
                 winds_10m=winds_10m, mslp=mslp, ....)

    # chunks of timesteps 
    dates = chunks(time, 10)
    # partial version of the function plot_files(), see underneath 
    plot_files_param = partial(plot_files, **args)
    p = Pool(8)
    p.map(plot_files_param, dates)

def plot_files(dates, **args):
    first = True
    for date in dates:
        #loop over dates, retrieve data from args, e.g. args['mslp'] and do the plotting 

if __name__ == "__main__":
    import time
    start_time = time.time()
    main()
    elapsed_time=time.time()-start_time
    print_message("script took " + time.strftime("%H:%M:%S", time.gmtime(elapsed_time)))
        

这曾经在 Python 2.7 上运行良好,但现在出现此错误

Traceback (most recent call last):
  File "plot_winds10m.py", line 135, in <module>
    main()
  File "plot_winds10m.py", line 79, in main
    p.map(plot_files_param, dates)
  File "lib/python3.8/multiprocessing/pool.py", line 364, in map
    return self._map_async(func, iterable, mapstar, chunksize).get()
  File "lib/python3.8/multiprocessing/pool.py", line 771, in get
    raise self._value
  File "lib/python3.8/multiprocessing/pool.py", line 537, in _handle_tasks
    put(task)
  File "lib/python3.8/multiprocessing/connection.py", line 206, in send
    self._send_bytes(_ForkingPickler.dumps(obj))
  File "lib/python3.8/multiprocessing/reduction.py", line 51, in dumps
    cls(buf, protocol).dump(obj)
TypeError: cannot pickle '_thread.lock' object

除了 Python 版本和软件包版本之外,唯一改变的是系统。我在 MacOS 上而不是在 Linux 上测试这个,但它应该不会有太大的不同,特别是因为这都是在 conda 环境中 运行。

有人知道如何解决这个问题吗?

(这里是 link 到 github 回购 https://github.com/guidocioni/icon_forecasts/blob/master/plotting/plot_winds10m.py

我想出了这个问题,以防万一有人来到这里急需答案。

问题是我使用 metpy.unit_array 进行的一些转换产生了一个 pint 数组,但出于某种原因它不是 pickable。当我在 partial 函数的 args 中传递这个数组时,我得到了错误。

尝试使用 .convert_units() 进行转换或只是从数据中提取数组部分(使用 .values.magnitude)确保我只传递了一个 numpy 数组或 DataArray 并且这些对象是可拾取的。