Мне жаль, что я не могу воспроизвести ошибку на более простом примере, а мой код слишком сложен для публикации. Если я запускаю программу в оболочке IPython вместо обычного Python, все работает хорошо.
Я посмотрел некоторые предыдущие заметки по этой проблеме. Все они были вызваны использованием пула для вызова функции, определенной в функции класса. Но это не так для меня.
Exception in thread Thread-3:
Traceback (most recent call last):
File "/usr/lib64/python2.7/threading.py", line 552, in __bootstrap_inner
self.run()
File "/usr/lib64/python2.7/threading.py", line 505, in run
self.__target(*self.__args, **self.__kwargs)
File "/usr/lib64/python2.7/multiprocessing/pool.py", line 313, in _handle_tasks
put(task)
PicklingError: Can't pickle <type 'function'>: attribute lookup __builtin__.function failed
Буду признателен за любую помощь.
Обновление : функция, которую я выбираю, определяется на верхнем уровне модуля. Хотя он вызывает функцию, которая содержит вложенную функцию. то есть f()
называет g()
звонки, у h()
которых есть вложенная функция i()
, а я звоню pool.apply_async(f)
. f()
, g()
, h()
Все определены на уровне верхней. Я попробовал более простой пример с этим шаблоном, и он работает, хотя.
dill
иpathos
. Однако мне не повезло ни с одним из решений при работе с vtkobjects :( Кому-нибудь удалось запустить код Python при параллельной обработке vtkPolyData?Ответы:
Вот список того, что можно мариновать . В частности, функции можно выбирать только в том случае, если они определены на верхнем уровне модуля.
Этот кусок кода:
выдает ошибку, почти идентичную той, которую вы опубликовали:
Проблема в том, что
pool
все методы используют amp.SimpleQueue
для передачи задач рабочим процессам. Все, что проходит через,mp.SimpleQueue
должно быть отборным иfoo.work
не может быть отборным, так как оно не определено на верхнем уровне модуля.Это можно исправить, определив функцию на верхнем уровне, которая вызывает
foo.work()
:Обратите внимание, что
foo
это можно выбрать, так какFoo
оно определено на верхнем уровне иfoo.__dict__
доступно для выбора.источник
pool = Pool()
строки здесь ). Я этого не ожидал, и это может быть причиной того, что проблема ОП осталась.functool.partial
к функции верхнего уровня также может быть засолен, даже если он определен внутри другой функции.Я бы использовал
pathos.multiprocesssing
вместоmultiprocessing
.pathos.multiprocessing
это вилка,multiprocessing
которая используетdill
.dill
Вы можете сериализовать практически все в Python, так что вы можете отправлять намного больше параллельно. Вpathos
форке также есть возможность работать напрямую с несколькими аргументными функциями, как вам нужно для методов класса.Получить
pathos
(и, если хотите,dill
) здесь: https://github.com/uqfoundationисточник
sudo pip install git+https://github.com/uqfoundation/dill.git@master
иsudo pip install git+https://github.com/uqfoundation/pathos.git@master
sudo
(из внешних источников, таких как GitHub). Вместо этого я бы порекомендовал запустить:pip install --user git+...
pip install pathos
не работает, к сожалению, и выдает следующее сообщение:Could not find a version that satisfies the requirement pp==1.5.7-pathos (from pathos)
pip install pathos
теперь работает иpathos
совместим с Python 3.multiprocess
это разветвление,multiprocessing
гдеdill
заменилиpickle
в нескольких местах в коде ... но, по сути, это все.pathos
предоставляет несколько дополнительных уровней API,multiprocess
а также имеет дополнительные бэкэнды. Но это суть этого.Как уже говорили другие,
multiprocessing
можно передавать только объекты Python рабочим процессам, которые можно обрабатывать. Если вы не можете реорганизовать свой код, как описано в unutbu, вы можете использоватьdill
расширенные возможности выбора / удаления для передачи данных (особенно данных кода), как показано ниже.Это решение требует только установки
dill
и никаких других библиотек, так какpathos
:источник
dill
иpathos
автор ... и, хотя вы правы, не так ли лучше, чище и гибче в использовании,pathos
как в моем ответе? Или, может быть, я немного предвзятый…pathos
на момент написания и хотел представить решение, которое очень близко к ответу. Теперь, когда я увидел ваше решение, я согласен, что это путь.Doh… I didn't even think of doing it like that.
так что это было круто.for
цикл. Обычно я вижу параллельную подпрограмму, берущую список и возвращающую список без цикла.Я обнаружил, что могу также сгенерировать именно этот вывод ошибок на идеально работающем фрагменте кода, пытаясь использовать на нем профилировщик.
Обратите внимание, что это было в Windows (где разветвление немного менее элегантно).
Я бегал:
И обнаружил, что удаление профилирования удалило ошибку, а размещение профилирования восстановило ее. Сводил меня с ума, потому что я знал, что код работал. Я проверял, обновлял ли что-то файл pool.py ... затем чувствовал себя погруженным и устранял профилирование, вот и все.
Публикация здесь для архивов на случай, если кто-то еще столкнется с ним.
источник
pass
не была «замаскирована».Когда эта проблема возникает с
multiprocessing
простым решением является переход отPool
кThreadPool
. Это может быть сделано без изменения кода, кромеЭто работает, потому что ThreadPool делит память с основным потоком, а не создает новый процесс - это означает, что травление не требуется.
Недостатком этого метода является то, что python не самый лучший язык для обработки потоков - он использует что-то, называемое Global Interpreter Lock, для обеспечения безопасности потока, что может замедлить некоторые варианты использования. Однако, если вы в первую очередь взаимодействуете с другими системами (выполняете команды HTTP, общаетесь с базой данных, записываете в файловые системы), тогда ваш код, скорее всего, не связан с процессором и не будет сильно ударяться. На самом деле, при написании тестов HTTP / HTTPS я обнаружил, что используемая здесь многопоточная модель имеет меньше накладных расходов и задержек, так как накладные расходы на создание новых процессов значительно превышают накладные расходы на создание новых потоков.
Так что, если вы обрабатываете массу вещей в пользовательском пространстве Python, это может быть не лучшим методом.
источник
Это также работает для массивов NumPy.
источник
Эта ошибка также возникнет, если внутри объекта модели есть встроенная функция, которая была передана в асинхронное задание.
Поэтому убедитесь, что переданные объекты модели не имеют встроенных функций. (В нашем случае мы использовали
FieldTracker()
функцию django-model-utils внутри модели для отслеживания определенного поля). Вот ссылка на соответствующую проблему GitHub.источник
Основываясь на решении @rocksportrocker, было бы целесообразно укропить при отправке и получении результатов.
источник