Не можете передать объекты PyDot через многопроцессорную функцию Pool.starmap ()? - PullRequest
0 голосов
/ 28 сентября 2019

У меня есть процесс, который делает это:

  • создает график в несколько тысяч, так как объекты 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 для передачи объектов, но это не так

...