Процессы, создаваемые этим пакетом, всегда могут взаимодействовать с помощью общесистемных инструментов, таких как сокеты и файлы fifo, с которыми мы встречались выше, тем не менее пакет multiprocessing также предоставляет свои переносимые инструменты обмена сообщениями, специально предусмотренные для организации взаимодействий между процессами, порождаемыми этим пакетом:
• Объект Pipe реализует анонимный канал, соединяющий два процесса. При вызове конструктора Pipe он возвращает два объекта Connection, представляющие концы канала. По умолчанию каналы являются двунаправленными и позволяют передавать и принимать любые объекты Python, поддерживающие возможность сериализации. В настоящее время в Unix они используют либо пару соединенных друг с другом сокетов, либо порождаются функцией os.pipe, с которой мы встречались выше, а в Windows они реализованы на основе именованных каналов, специфических для этой платформы. Однако, как и объект Process, описанный выше, переносимый API объекта Pipe скрывает все эти тонкости от вызывающей программы.
• Объекты Value и Array реализуют общую память процессов/потоков, используемую для обмена данными между процессами. Конструкторы этих объектов возвращают одиночный объект и массив объектов, созданные с помощью модуля ctypes в разделяемой памяти, доступ к которой синхронизируется по умолчанию.
• Объект Queue играет роль списка FIFO объектов Python, допускающий возможность работы с множеством производителей и потребителей. По сути, эта очередь является каналом, снабженным механизмом блокировки для координации попыток доступа к ней, и наследует ограничения объекта Pipe, связанные с требованием к поддержке сериализации объектами, помещаемыми в очередь.
Все эти механизмы обеспечивают возможность безопасной работы с нескольким процессами, поэтому они часто играют роль точек синхронизации взаимодействий и позволяют отказаться от использования низкоуровневых инструментов, таких как блокировки, работая сходным с очередями в потоках, с которыми мы встречались выше, образом. Как обычно, канал (или их пара) может использоваться для реализации модели запрос/ответ. Очереди поддерживают более гибкие модели взаимодействий — фактически для преодоления ограничений GIL, вместо потоков выполнения в графическом интерфейсе можно было бы использовать объекты Process и Queue из пакета multiprocessing, и порождать с их помощью долгоживущие процессы, обменивающиеся результатами. Как упоминалось выше, хотя при таком подходе на некоторых платформах на запуск процессов тратится дополнительное время — в сравнении с потоками выполнения, зато он обеспечивает по- настоящему параллельное выполнение задач, если это позволяет сама платформа.
Важное замечание: каналы (и, соответственно, очереди), реализованные в этом пакете, выполняют сериализацию объектов, передаваемых через них, благодаря чему они могут быть реконструированы в принимающем процессе (как мы уже видели, в Windows принимающий процесс может выполняться под управлением полностью независимой копии интерпретатора Python). По этой причине они не поддерживают объекты, которые нельзя сериализовать. Как отмечалось выше, к ним относятся некоторые вызываемые объекты, такие как связанные методы и lambda-функции (программный код, нарушающий эти ограничения, смотрите в файле multi—badq.py в пакете с примерами для этой книги). Передача объектов с системной информацией также может терпеть неудачу. Большинство остальных типов объектов Python, включая классы и простые функции, прекрасно передаются через каналы и очереди.
Кроме того, имейте в виду, что из-за необходимости сериализации объекты, передаваемые с помощью этих инструментов, в принимающем процессе фактически являются копиями — прямые изменения в таких объектах не видимы передавшему их процессу. Это вполне объяснимо, если вспомнить, что данный пакет запускает независимые процессы с их собственными областями памяти — информация не может так же свободно передаваться между ними, как в потоках выполнения, независимо от используемого инструмента IPC.
Использованная литература:
Марк Лутц — Программирование на Python, 4-е издание, I том, 2011