Почему `multiprocessing . Process ( ) ‘ создает промежуточный процесс в Windows? — Переполнение стека.Process()` создает промежуточный процесс в Windows?

#python #windows

#python #Windows

Вопрос:

Я изучаю отношения родительско-дочерних процессов в Windows 10 и написал скрипт на python 3.7.2 для создания дерева дочерних процессов. Я использую multiprocessing.Process() для создания дочерних процессов. Каждый process регистрирует свой process.id , process.id своего родителя и process.id созданных им дочерних процессов.

На моем локальном ноутбуке под управлением macOS это работает так, как ожидалось; process 1 создает процессы 2 и 3 , и 2 и 3 каждый отчет, который является их родительским 1 . Однако в Windows process 1 создает два процесса, скажем, A и B , а процессы 2 и 3 сообщают, что A и B являются их родителями соответственно. Почему создаются эти промежуточные процессы? Почему бы просто не создать 2 и 3 напрямую?

Вот сценарий и выходные данные первых нескольких файлов журнала для каждой системы:

 import sys
import os
import time
from multiprocessing import Process

tree = {
    1 : [2, 3],
    2 : [4, 5, 6],
    3 : [7, 8],
    7 : [9, 10]
}

def start_child(my_id):
    children_ids = tree.get(my_id, None)

    child_processes = []
    if children_ids:
        for child_id in children_ids:
            child = Process(target=start_child, args=(child_id,))
            child_processes.append(child)
            child.start()

    current_dir = os.path.dirname(os.path.realpath(__file__))
    with open(f'{current_dir}/{my_id}.log', 'w') as out:
        out.write(f"I am {os.getpid()}.nMy parent process is {os.getppid()}.n")
        for child in child_processes:
            out.write(f"I spawned process {child.pid}, named {child.name}.n")

    time.sleep(50)
    for child in child_processes:
        child.join()

if __name__ == "__main__":
    start_child(1)
  

Первые три журнала из macOS (ожидаемое поведение):

 # 1.log
I am 40847.
My parent process is 40552.
I spawned process 40857.
I spawned process 40858.
  
 # 2.log
I am 40857.
My parent process is 40847.
I spawned process 40859.
I spawned process 40860.
I spawned process 40862.
  
 # 3.log
I am 40858.
My parent process is 40847.
I spawned process 40861.
I spawned process 40863.
  

Первые три журнала из Windows 10 (неожиданное поведение):

 # 1.log
I am 6908.
My parent process is 1392.
I spawned process 7608.
I spawned process 5212.
  
 # 2.log
I am 6512.
My parent process is 7608.
I spawned process 10780.
I spawned process 5520.
I spawned process 1176.
  
 # 3.log
I am 2032.
My parent process is 5212.
I spawned process 3424.
I spawned process 7776.
  

Как вы можете видеть в Windows, родительские process.id для процессов 2 и 3 являются дочерними для процесса 1 , а не сам процесс 1 .

Я уверен, что мог бы углубиться в multiprocessing реализацию для Windows, но я надеюсь, что кто-то другой уже это сделал…

Комментарии:

1. Я предполагаю, что вы используете виртуальную среду. Новый исполняемый файл venv launcher устанавливается как sys.executable , что полезно в целом, но является проблемой для многопроцессорной обработки. Эта проблема была решена в 3.7.3 с добавлением нового sys._base_executable атрибута, который используется внутри multiprocessing.

2. @eryksun Это правильно, я использую виртуальную среду. И похоже, что обновление до 3.7.3 устраняет многопроцессорность. Спасибо за совет!