#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
, и эти объекты можно выбрать.