Скрипт, использующий многопроцессорную обработку с частичным сбоем и отображением на Python > 3, отлично работает на 2.7, не может удалить ‘_thread.lock’

#python #python-3.x #multiprocessing #functools

#python #python-3.x #многопроцессорная обработка #функциональные средства

Вопрос:

До сегодняшнего дня я использовал следующий код на Python 2.7 для распараллеливания создания множества изображений PNG с matplotlib . Сегодня я попытался переместить все на 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.

У кого-нибудь есть идея о том, как это исправить?

(вот ссылка на репозиторий github https://github.com/guidocioni/icon_forecasts/blob/master/plotting/plot_winds10m.py )

Ответ №1:

Я разобрался с проблемой на случай, если кто-нибудь придет сюда, отчаянно нуждаясь в ответе.

Проблема в том, что некоторые преобразования, которые я выполнял, metpy.unit_array создают pint массив, который по какой-то причине не является pickable . Когда я затем передавал этот массив в args функции partial , я получал ошибку.

Попытка вместо этого выполнить преобразование с помощью .convert_units() или просто извлечь часть массива из данных (либо с помощью .values or .magnitude ) гарантировала, что я передаю только numpy массив или DataArray , и эти объекты можно выбрать.