Сообщить об ошибке.

Класс Process() модуля multiprocessing в Python

Создание отдельного процесса, запуск задачи и получение результата выполнения

Синтаксис:

import multiprocessing

proc = multiprocessing.Process(group=None, target=None, 
                               name=None, args=(), 
                               kwargs={}, *, daemon=None)

Параметры:

Конструктор всегда следует вызывать с ключевыми аргументами.

  • group=None - не используется модулем,
  • target=None - вызываемый объект (функция),
  • name=None - имя процесса,
  • args=() - аргументы для target,
  • kwargs={} - ключевые аргументы для target,
  • daemon=None - флаг для демонизации процесса.

Возвращаемое значение:

Описание:

Класс Process() модуля multiprocessing запускает вызываемый объект target на исполнение, который будет выполняется в отдельном процессе/ядре процессора.

Есть два способа запустить какое либо действие:

  • Передать вызываемый объект (функцию) target в конструктор.
  • Переопределить метод Process.run() в подклассе.

Внимание! Никакие другие методы не должны переопределяться в подклассе (кроме конструктора). Другими словами, можно переопределять только методы __init__() и Process.run() этого класса.

Объект Process имеет эквиваленты всех методов объекта Thread().

Аргумент group всегда должна быть None; он существует исключительно для совместимости с классом threading.Thread().

Аргумент target - это вызываемый объект, который будет вызываться методом Process.run(). По умолчанию это None, что означает, что ничего не вызывается. По умолчанию в вызываемый объект target не передаются его аргументы.

Аргумент name - это имя процесса, подробнее смотрите атрибут Process.name.

Аргумент args - это кортеж аргументов для целевого вызова target. Аргумент kwargs - это словарь ключевых аргументов для целевого вызова target.

Если предоставлен ключевой аргумент daemon, то он устанавливает флаг демона процесса значение True или False. Если daemon=None (по умолчанию), этот флаг будет унаследован от процесса создателя.

Если подкласс переопределяет конструктор класса multiprocessing.Process(), то необходимо вызывать конструктор базового класса Process.__init__(), прежде чем делать что-либо еще с процессом.

Обратите внимание, что методы Process.start(), Process.join(), Process.is_alive(), Process.terminate() и Process.exitcode должны вызываться только процессом, создавшим этот объект процесса.

Методы объекта Process.

Объекты Process представляют собой действия, которые выполняются в отдельном процессе.


Process.run():

Метод Process.run() представляет активность процесса.

Можно переопределить этот метод в своем подклассе. Стандартный метод Process.run() вызывает вызываемый объект, переданный конструктору в качестве целевого аргумента target, с позиционными и ключевыми аргументами, взятыми из аргументов args и kwargs соответственно.

Метод Thread.run() можно переопределить в пользовательском подклассе. Например:

import multiprocessing, time

class Worker(multiprocessing.Process):
    
    def __init__(self, num_thread):
        # вызываем конструктор базового класса
        super().__init__()
        # определяем аргументы собственного класса
        self.num_thread = num_thread
        
    def run(self):
        # основной код, который должен выполняться 
        # в отдельных процессах будет здесь
        print(f'Старт процесса №{self.num_thread}')
        time.sleep(1)
        print(f'Завершение работы процесса №{self.num_thread}')

for i in range(2):
    # Создаем экземпляры класса 'Worker()'
    th = Worker(i)
    # запускаем процессы
    th.start()
    
# Старт процесса №0
# Старт процесса №1
# Завершение работы процесса №0
# Завершение работы процесса №1

Process.start():

Метод Process.start() запускает экземпляр Process в отдельном процессе/ядре процессора.

Этот метод должен быть вызван не более одного раза для каждого объекта процесса. Он организует вызов метода Process.run() объекта в отдельном процессе/ядре процессора.

Дополнительно, смотрите описание этого метода у объекта Thread, примеры кода аналогичны.

Process.join([timeout]):

Метод Process.join() ждет, пока не завершится процесс.

Если необязательный аргумент timeout=None (по умолчанию), то процесс, из которого вызван этот метод, блокируется до тех пор, пока не завершится процесс, у которого вызван этот метод. Проще говоря, если вызвать метод Process.join() для создаваемых процессов из основного процесса программы, то дальнейшее выполнение программы будет заблокировано, пока созданные процессы не завершаться.

Если тайм-аут timeout является положительным числом, то процесс блокируется не более чем на величину секунд, указанную в timeout. Обратите внимание, что метод возвращает None, если его процесс завершается или если время ожидания метода истекает. Проверьте код выхода процесса Process.exitcode, чтобы определить, завершился ли он.

К процессу можно присоединяться много раз.

Процесс не может присоединиться к самому себе, так как это вызовет взаимоблокировку. Попытка присоединиться к процессу до его запуска является ошибкой.

Дополнительно, смотрите описание этого метода у объекта Thread, примеры кода аналогичны.

Process.name:

Атрибут Process.name это имя процесса и представляет собой строку, которая используется только для идентификации. У имени нет семантики.

Несколько процессов могут иметь одно и то же имя (можно присваивать).

Начальное имя задается конструктором класса. Если в конструктор не передан аргумент name, то имена порожденных процессов будет выглядеть как "Process-N1:N2:...:Nk", где каждый Nk является N-м потомком своего родителя.

Дополнительно, смотрите описание этого метода у объекта Thread, примеры кода аналогичны.

Process.is_alive():

Метод Process.is_alive() проверяет, является ли процесс живым.

Грубо говоря, объект процесса является живым с момента вызова метода Process.start() и до завершения порожденного дочернего процесса.

Process.daemon:

Атрибут Process.daemon флаг демона процесса, логическое значение. Этот атрибут должен быть установлен перед вызовом метода Process.start().

Начальное значение наследуется от процесса создателя.

Когда процесс завершается, он пытается завершить все свои демонические дочерние процессы.

Обратите внимание, что демоническому процессу не разрешается создавать дочерние процессы. Так как если демонический процесс будет прерван выходом из родительского процесса, то демонический процесс оставил бы свои дочерние процессы "сиротами". Кроме того, это не демоны или службы Unix, это обычные процессы, которые будут завершены (но не присоединены), если завершились не-демонические процессы.

Process.pid:

Атрибут Process.pid возвращает идентификатор процесса. До того, как процесс будет порожден, это будет None.

Process.exitcode:

Атрибут Process.exitcode возвращает код выхода порожденного процесса. Значение будет None, если процесс еще не завершен.

Отрицательное значение -N указывает, что дочерний элемент был прерван сигналом N.

Process.authkey:

Атрибут Process.authkey ключ аутентификации процесса, представляет из себя байтовую строку.

При инициализации модуля multiprocessing, основному процессу присваивается случайная строка с помощью os.urandom().

Когда создается объект процесса, то он наследует ключ аутентификации своего родительского процесса, хотя это может быть изменено путем установки атрибута authkey в другую байтовую строку.

Process.sentinel:

Атрибут Process.sentinel числовой дескриптор системного объекта, который станет "готовым" по завершении процесса.

Можно использовать это значение, если необходимо дождаться нескольких событий одновременно, используя multiprocessing.connection.wait(). Вообще это проще сделать вызвав метод Process.join() у каждого из создаваемых процессов, результатов которых надо дождаться.

В Windows это дескриптор ОС, который можно использовать с семейством вызовов API WaitForSingleObject и WaitForMultipleObjects. В Unix это файловый дескриптор, который можно использовать с примитивами из модуля select.

Process.terminate():

Метод Process.terminate() завершает процесс. В Unix это делается с помощью сигнала SIGTERM, в Windows используется TerminateProcess().

Обратите внимание, что обработчики выхода, предложения tru/finally и т. д. не будут выполняться.

Обратите внимание, что дочерние процессы, процесса для которого вызван метод Process.terminate() не будут завершены - они просто станут "осиротевшими".

Предупреждение. Если этот метод используется, когда связанный процесс использует канал multiprocessing.Pipe или очередь multiprocessing.Queue, то канал или очередь могут быть повреждены и могут стать непригодными для использования другим процессом. Точно так же, если процесс получил блокировку или другой примитив синхронизации, то его завершение может привести к взаимоблокировке других процессов.

Process.kill():

Метод Process.kill() делает то же самое, что и метод Process.terminate(), но с использованием сигнала SIGKILL в Unix.

Новое в Python 3.7.

Process.close():

Метод Process.close() закрывает объект Process, освободив все связанные с ним ресурсы. Если базовый процесс все еще выполняется, то возникает исключение ValueError.

После успешного завершения Process.close(), большинство других методов и атрибутов объекта Process вызовут исключение ValueError. .

Примеры использования некоторых методов объекта Process:

>>> import multiprocessing, time, signal
>>> p = multiprocessing.Process(target=time.sleep, args=(1000,))
>>> print(p, p.is_alive())
# <Process ... initial> False
>>> p.start()
>>> print(p, p.is_alive())
# <Process ... started> True
>>> p.terminate()
>>> time.sleep(0.1)
>>> print(p, p.is_alive())
# <Process ... stopped exitcode=-SIGTERM> False
>>> p.exitcode == -signal.SIGTERM
# True

Общий пример создания процессов классом Process.

import multiprocessing

def worker(i):
    """proces worker function"""
    print(f'Worker-{i}')

procs = []
# запускаем функцию 'worker()' 
# для выполнения в 5-ти потоках
for i in range(5):
    p = multiprocessing.Process(target=worker, args=(i,))
    procs.append(p)
    p.start()
    
print('Ждем результаты...')
# блокируем дальнейшее выполнение программы
# пока не закончат выполняться все 5 потоков
[proc.join() for proc in procs]
print('Результаты получены.')

# Worker-0
# Worker-1
# Ждем результаты...
# Worker-2
# Worker-3
# Worker-4
# Результаты получены.