Ответ
Класс multiprocessing.Process в Python используется для создания и управления дочерними процессами. Его основная цель — выполнение CPU-bound задач (интенсивных вычислений) в параллельном режиме, что позволяет обойти ограничение Global Interpreter Lock (GIL) и эффективно использовать все ядра процессора.
В отличие от потоков (threading.Thread), которые выполняются в рамках одного процесса и разделяют одну память (и GIL), каждый Process имеет собственное адресное пространство и свой экземпляр интерпретатора Python.
Базовый пример использования:
import multiprocessing
import time
def worker(name):
"""Функция, которая будет выполняться в дочернем процессе."""
print(f'Процесс {name} запущен.')
time.sleep(2)
print(f'Процесс {name} завершен.')
if __name__ == '__main__':
# Создание объекта процесса
p = multiprocessing.Process(target=worker, args=('Worker-1',))
# Запуск процесса
p.start()
print('Основной процесс продолжает работу.')
# Ожидание завершения дочернего процесса
p.join()
print('Дочерний процесс завершился, основной процесс закончен.')
Ключевые особенности и правила:
if __name__ == '__main__':: Эта конструкция обязательна в Windows и рекомендуется во всех ОС. Она предотвращает рекурсивное создание дочерних процессов при импорте модуля.targetиargs: В конструкторProcessпередается целевая функция (target) и кортеж ее аргументов (args).start(): Метод запускает выполнение функции в новом процессе.join(): Метод блокирует выполнение основного процесса до тех пор, пока дочерний процесс не завершится. Это необходимо для синхронизации.- Межпроцессное взаимодействие (IPC): Поскольку процессы изолированы, для обмена данными между ними используются специальные механизмы, такие как
Queue,PipeилиManagerиз модуляmultiprocessing.
Ответ 18+ 🔞
А, ну вот, слушай, смотри, сейчас я тебе объясню про эту штуку — multiprocessing.Process. Это ж, блядь, как молоток для гвоздей, только для твоего процессора, когда ему надо впахивать по-настоящему, а не в одну дырку тыкаться.
Представь себе: у тебя есть одна задача, которая жрёт процессорное время, как голодный студент в столовой — это CPU-bound задача, ёпта. А в Python есть такая пакость — GIL, глобальная блокировка интерпретатора. Она делает так, что даже если у тебя 16 ядер, твои потоки (threading.Thread) будут толкаться, как пьяные в очереди за шаурмой, по одному. А вот процессы — это отдельные, блядь, вселенные. У каждого свой интерпретатор, своя память, и GIL им похуй, они на разных ядрах могут работать.
Смотри, как это выглядит на практике, простейший пример:
import multiprocessing
import time
def worker(name):
"""Функция, которая будет выполняться в дочернем процессе."""
print(f'Процесс {name} запущен.')
time.sleep(2)
print(f'Процесс {name} завершен.')
if __name__ == '__main__':
# Создание объекта процесса
p = multiprocessing.Process(target=worker, args=('Worker-1',))
# Запуск процесса
p.start()
print('Основной процесс продолжает работу.')
# Ожидание завершения дочернего процесса
p.join()
print('Дочерний процесс завершился, основной процесс закончен.')
Теперь, сука, важные моменты, чтобы не наступить на грабли:
if __name__ == '__main__':: Это, блядь, святое. Особенно в Винде, но и в линуксе тоже не помешает. Без этого защитного заклинания можешь получить рекурсивный пиздец, когда процессы начнут плодиться, как кролики, при импорте. В рот меня чих-пых, просто запомни и пиши всегда.targetиargs:target— это функция, которую ты засовываешь в процесс, как патрон в ствол.args— это кортеж с аргументами для неё. Если один аргумент — не забудь запятую, а то получишь хуй с горы, а не кортеж.start(): Тыкаешь в эту кнопку — и понеслась, процесс отпочковывается и начинает свою жизнь.join(): А это, понимаешь, как стоять у подъезда и ждать, пока твой друг допьёт пиво в гостях. Основной процесс встанет на паузу и будет ждать, пока этот дочерний не закончит свои дела. Без этого твой основной скрипт может уже всё посчитать и завершиться, а дочерний процесс так и останется висеть, как манда с ушами.- Общение между процессами: Вот тут самое интересное. Они же изолированы, как монахи в кельях. Не могут просто так взять и пошептаться через переменную. Для этого есть специальные штуки —
Queue(очередь),Pipe(труба) илиManager. Через них они передают друг другу записки, как на уроке.
Короче, если тебе надо реально грузить процессор — это твой выбор. Потоки для I/O операций (сеть, диск), а процессы — для тяжёлых вычислений. Всё, вопрос закрыт.