У меня есть процесс, который делает это:
- создает график в несколько тысяч, так как объекты PyDot (особенно
pydot.Dot(graph_type='digraph', simplify=False)
) - анализируют ребра и узлы для улучшения некоторой информации (установить URL-адреса и тому подобное)
- генерирует изображение SVG для каждого графика
часть генерации SVG является самой медленной, так как она вызывает /usr/bin/dot
и может потребоваться даженесколько минут для самых сложных графиков.
, поэтому у меня возникла блестящая (!) идея исследовать использование многопроцессорной обработки Pool
(чтобы я мог ограничить возможность параллельной обработки), но я наткнулся на некоторые проблемы, которые яне могу понять.
Я написал простую функцию, которая бы выполняла параллельную задачу:
def write_svg_graph(graph, outfile):
with open(outfile, 'wb') as f:
f.write(graph.create(format='svg'))
сохранил мои пары (PyDot,) в списке work
и затем настроил mpкак:
with mp.Pool(mp.cpu_count()-2) as p:
p.starmap(write_svg_graph, work)
и здесь начинаются проблемы;Последовательный запуск этого кода (поэтому просто вызовите write_svg_graph
) из одного и того же скрипта работает просто отлично, но с mp я получаю:
multiprocessing.pool.RemoteTraceback:
"""
Traceback (most recent call last):
File "/usr/lib/python3.7/multiprocessing/pool.py", line 121, in worker
result = (True, func(*args, **kwds))
File "/usr/lib/python3.7/multiprocessing/pool.py", line 47, in starmapstar
return list(itertools.starmap(args[0], args[1]))
File "myscript.py", line 146, in write_svg_graph
f.write(graph.create(format='svg'))
File "/usr/lib/python3/dist-packages/pydot.py", line 1882, in create
prog = self.prog
AttributeError: 'Dot' object has no attribute 'prog'
"""
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "myscript.py", line 179, in <module>
p.starmap(write_svg_graph, work)
File "/usr/lib/python3.7/multiprocessing/pool.py", line 276, in starmap
return self._map_async(func, iterable, starmapstar, chunksize).get()
File "/usr/lib/python3.7/multiprocessing/pool.py", line 657, in get
raise self._value
AttributeError: 'Dot' object has no attribute 'prog'
, что не имеет смысла (для меня).поэтому я изменяю функцию на:
def write_svg_graph(graph, outfile):
graph.set_prog('/usr/bin/dot')
with open(outfile, 'wb') as f:
f.write(graph.create(format='svg'))
(явно задает свойство prog
), но:
multiprocessing.pool.RemoteTraceback:
"""
Traceback (most recent call last):
File "/usr/lib/python3.7/multiprocessing/pool.py", line 121, in worker
result = (True, func(*args, **kwds))
File "/usr/lib/python3.7/multiprocessing/pool.py", line 47, in starmapstar
return list(itertools.starmap(args[0], args[1]))
File "myscript.py", line 146, in write_svg_graph
f.write(graph.create(format='svg'))
File "/usr/lib/python3/dist-packages/pydot.py", line 1898, in create
for img in self.shape_files:
AttributeError: 'Dot' object has no attribute 'shape_files'
"""
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "myscript.py", line 179, in <module>
p.starmap(write_svg_graph, work)
File "/usr/lib/python3.7/multiprocessing/pool.py", line 276, in starmap
return self._map_async(func, iterable, starmapstar, chunksize).get()
File "/usr/lib/python3.7/multiprocessing/pool.py", line 657, in get
raise self._value
AttributeError: 'Dot' object has no attribute 'shape_files'
отсутствует другое свойство!но если я проверяю тип объекта, полученного в write_svg_file
, это PyDot.
Кто-нибудь знает, что происходит, как распараллелить генерацию SVG из объектов PyDot с помощью многопроцессорной обработки?Спасибо!:)
ОБНОВЛЕНИЕ 1 : после небольшого исследования кажется, что mp нужно передать объекты, используя pickle
их, и объекты Dot не являются маринованными:
In [541]: g
Out[541]: <pydot.Dot at 0x7f9c29cd2358>
In [542]: g.prog
Out[542]: 'dot'
In [543]: gg = pickle.loads(pickle.dumps(g))
In [544]: gg == g
Out[544]: False
In [545]: gg.prog
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-545-4ab0fd4f9bc9> in <module>()
----> 1 gg.prog
AttributeError: 'Dot' object has no attribute 'prog'
Как мне пойти и исправить pydot для этого?
ОБНОВЛЕНИЕ 2 : Я сообщил о некоторых своих выводах в https://github.com/pydot/pydot/issues/217, я думаю, что мы не можем пройтиpydot через mp из-за того, что они не были закончены замаскированными.было бы здорово, если бы mp поддерживал использование dill
вместо pickle
для передачи объектов, но это не так