Процессы в python

В python процессы применяют для распараллеливания тяжелых вычислений: вычисление хэшей, работы с матрицами, обработки изображений и иных подобных операций. Создавать процессы просто: достаточно создать объект класса Process и передать в него callable-объект, который должен запуститься в отдельном процессе.

Процессом обычно называют запущенную программу. Для запуска операционная система выделяет определенную область памяти. Обычно она изолирована, поэтому процессы не могут влиять на работу друг друга, изменяя области памяти, которые им не принадлежат.

В python процессы применяют для распараллеливания тяжелых вычислений: вычисление хэшей, работы с матрицами, обработки изображений и иных подобных операций. Создавать процессы просто: достаточно создать объект класса Process и передать в него callable-объект, который должен запуститься в отдельном процессе.

Рассмотрим базовый пример:

1import time 2import os 3 4from multiprocessing import Process, current_process 5 6 7def foo(text: str) -> None: 8 time.sleep(3) 9 10 print('[foo] process name:', current_process().name) 11 print('[foo] process pid:', current_process().pid) 12 print('msg:', text) 13 14 15if __name__ == '__main__': 16 print('Main process pid:', os.getpid()) 17 18 p = Process(target=foo, args=('Hello world', ), name='foo-process') 19 process_pid = p.pid 20 process_is_alive = p.is_alive() 21 print(f'Process with pid: {process_pid} is alive: {process_is_alive}') 22 23 print('Process started') 24 p.start() 25 process_pid = p.pid 26 process_is_alive = p.is_alive() 27 print(f'Process with pid: {process_pid} is alive: {process_is_alive}') 28 29 print('Waiting for the process ends...') 30 p.join() 31 process_pid = p.pid 32 process_is_alive = p.is_alive() 33 print(f'Process with pid: {process_pid} is alive: {process_is_alive}') 34 35 print('End program')

Вывод к консоль:

1Main process pid: 24569 2Process with pid: None is alive: False 3Process started 4Process with pid: 24570 is alive: True 5Waiting for the process ends... 6[foo] process name: foo-process 7[foo] process pid: 24570 8msg: Hello world 9Process with pid: 24570 is alive: False 10End program

Также, пока выполняется скрипт, во втором окне терминала выполните команду ps aux | grep <pid_number> для каждого полученного pid. В результате будет примерно следующее:

1~> ps aux | grep 24569 2darksto+ 24569 0.6 0.0 28316 11192 ? S 14:58 0:00 ~/PycharmProjects/edu/async-python-sprint-1/.venv/bin/python ~/.config/JetBrains/PyCharm2022.3/scratches/scratch.py 3darksto+ 24578 0.0 0.0 17868 2280 pts/0 S+ 14:58 0:00 grep --color=auto 24569 4 5~> ps aux | grep 24570 6darksto+ 24570 0.0 0.0 28316 8968 ? S 14:58 0:00 ~/PycharmProjects/edu/async-python-sprint-1/.venv/bin/python ~/.config/JetBrains/PyCharm2022.3/scratches/scratch.py 7darksto+ 24590 0.0 0.0 17868 2312 pts/0 S+ 14:58 0:00 grep --color=auto 24570

Видим, что в один момент времени существуют два процесса, с соответсвующими pid.

Разберем пример кода по шагам. Вначале добавляем необходимые импорты и функцию foo. Внутри функции добавляем вывод названия и pid текущего процесса, в котором выполняется функция.

Начинаем основной блок программы. С помощью модуля os выводим pid основного процесса.

Создаем экземпляр класса Process, передав в него, через параметр target, callable объект (функцию foo), ее аргументы и название процесса. Метод is_alive() позволяет определить запущен процесс или нет. С помощью метода start() запускаем процесс, а добавление метода join() в основной код, позволяет дождаться завершения дочернего процесса.

Если необходимо выполнить прерывание работы процесса из основной части программы, не дожидаясь его выполнения можно использовать метод процесса terminate().

Для сериализации и десериализации объектов при взаимодействии с процессами используется модуль pickle, который работает только с примитивными типами – числами, строками, словарями, функциями и т.п. Детальнее о взаимодействии между процессами можно прочитать в нашей статье.

Заключение

Рассмотрим еще раз основные достоинста и недостатки процессов в python.

Достоинства

  • Возможность использовать все доступные ядра процессора
  • GIL не накладывает своих ограничений
  • У каждого процесса своя область памяти
  • Есть возможность прервать процесс
  • Подходит для тяжелых вычислений

Недостатки

  • Более сложный интерфейс и больше накладные расходы
  • Большое потребление памяти
Тэги:
python
Дата публикации:
21.09.2023

avatar
master
Admin

Похожие статьи