Мы рассматриваем рефакторинг крупного приложения со сложным GUI, который изолируется отделенным способом от бэкенда, для использования нового (Python 2.6) модуль многопроцессорной обработки. GUI/внутренний интерфейс использует Очереди с Объектами сообщения, которыми обмениваются в обоих направлениях.
Одна вещь я только что завершил (предварительно, но не стесняйтесь подтверждать это), то, что "объектные идентификационные данные" не были бы сохранены через многопроцессорный интерфейс. В настоящее время, когда наш GUI публикует сообщение к бэкенду, он ожидает возвращать то же сообщение с результатом, присоединенным как атрибут. Это использует объектные идентификационные данные (if received_msg is message_i_sent:
) для идентификации сообщений возврата в некоторых случаях... и это кажется вероятным не работать с многопроцессорной обработкой.
Этот вопрос состоит в том, чтобы спросить, какие "глюки" как это Вы видели в фактическом использовании или можете предположить, что можно было бы встретиться в наивном использовании многопроцессорного модуля, особенно в рефакторинге существующего приложения единственного процесса. Укажите, основан ли Ваш ответ на фактическом опыте. Бонусные очки для обеспечения применимого обходного решения для проблемы.
Править: Хотя мое намерение с этим вопросом состояло в том, чтобы собрать описания проблем в целом, я думаю, что сделал две ошибки: Я сделал это общественной Wiki из запуска (который, вероятно, заставляет многих людей проигнорировать его, поскольку они не поймут мысли репутации), и я включал также определенный пример, который - в то время как я ценю ответы - вероятно, заставил многих людей пропустить запрос на общие ответы. Я, вероятно, перефразирую и повторно спрошу это в новом вопросе. На данный момент я принимаю, что один ответ как лучше всего просто закрывает вопрос насколько он принадлежит определенному примеру, который я включал. Благодаря тем, кто действительно отвечал!
Я не использовал саму многопроцессорность, но представленные проблемы аналогичны опыту, который я испытал в двух других областях: распределенных системах и объектных базах данных. Идентичность объекта Python может быть и благословением, и проклятием!
Что касается общих подводных камней, это помогает, если приложение, которое вы реорганизуете, может признать, что задачи обрабатываются асинхронно. В противном случае вы, как правило, будете управлять блокировками, и большая часть производительности, которую вы могли бы получить при использовании отдельных процессов, будет потеряна из-за ожидания этих блокировок. Я также предлагаю вам потратить время на создание каркаса для отладки между процессами. Поистине асинхронные процессы, как правило, делают гораздо больше, чем может вместить и проверить разум - или, по крайней мере, мой разум!
Для конкретного случая, описанного выше, Я бы управлял идентификацией объекта на границе процесса, когда элементы ставились в очередь и возвращались. При отправке задачи на обработку аннотируйте задачу с помощью id () и сохраняйте экземпляр задачи в словаре, используя id () в качестве ключа. Когда задача обновлена / завершена, извлеките точную задачу обратно с помощью id () из словаря и примените к ней недавно обновленное состояние. Теперь точная задача и, следовательно, ее личность будет сохранена.
Вы можете попробовать пакет persistent
из моего проекта GarlicSim. Это LGPL'ed.
http://github.com/cool-RR/GarlicSim/tree/development/garlicsim/garlicsim/misc/persistent/
(Основной модуль в нём - persistent.py
)
Я часто использую его так:
# ...
self.identity = Persistent()
Тогда у меня есть идентификатор, который сохраняется во всех процессах.
.Ну, конечно же, тестирование на идентичность на несинглонированном объекте (например, на несинглонированном объекте) (es. "a is None" или "a is False") обычно не является хорошей практикой - это может быть быстро, но действительно быстрый обходной путь будет заключаться в обмене "is" на "==" и использовании инкрементального счетчика для определения идентичности:
# this is not threadsafe.
class Message(object):
def _next_id():
i = 0
while True:
i += 1
yield i
_idgen = _next_id()
del _next_id
def __init__(self):
self.id = self._idgen.next()
def __eq__(self, other):
return (self.__class__ == other.__class__) and (self.id == other.id)
Это может быть идеей.
Кроме того, имейте в виду, что если у вас есть тонны "рабочих процессов", потребление памяти может быть намного больше, чем при потокообразном подходе.
.