Мультиобработка вопроса в Python.Windows против Linux - PullRequest
0 голосов
/ 15 марта 2019
import random
import os
from multiprocessing import Process

num = random.randint(0, 100)

def show_num():
    print("pid:{}, num is {}".format(os.getpid(), num))

if __name__ == '__main__':
    print("pid:{}, num is {}".format(os.getpid(), num))
    p = Process(target=show_num)
    p.start()
    p.join()
    print('Parent Process Stop')

Приведенный выше код показывает основные способы создания процесса.Если я запускаю этот сценарий в среде Windows, переменная num отличается в родительском и дочернем процессах.Однако переменная num одинакова при запуске сценария между средой Linux.Я понимаю, что их механизм создания процесса отличается.Например, система Windows не имеет метода fork.Но может ли кто-нибудь дать мне более подробное объяснение их различий?Большое спасибо.

1 Ответ

0 голосов
/ 15 марта 2019

Разница, объясняющая поведение, описанное в вашем посте, именно то, что вы упомянули: метод запуска , используемый для создания процесса. В ОС Unix-стиля по умолчанию используется fork. В Windows единственным доступным вариантом является spawn.

вилка
Как описано в разделе «Обзор» этой вики-страницы (в несколько ином порядке):

Операция fork создает отдельное адресное пространство для дочернего элемента. дочерний процесс имеет точную копию всех сегментов памяти родительский процесс .

Дочерний процесс вызывает системный вызов exec для наложения себя на другая программа: она прекращает выполнение своей прежней программы в пользу другой.

Это означает, что при использовании fork дочерний процесс уже имеет переменную num в своем адресном пространстве и использует ее. random.randint(0, 100) не вызывается снова.

порождение
Как описывают многопроцессорные документы:

Родительский процесс запускает новый процесс интерпретатора Python.

В этом новом процессе интерпретатора выполняется модуль, из которого создается потомок. Упрощенно, это делает python.exe your_script.py во второй раз. Следовательно, новая переменная num создается в дочернем процессе, присваивая ему возвращаемое значение другого вызова random.randint(0, 100). Поэтому весьма вероятно, что содержание num отличается между процессами.
Это, кстати, и причина, по которой вам абсолютно необходимо для защиты создания и запуска процесса с идиомой if __name__ == '__main__' при использовании spawn в качестве метода запуска, в противном случае вы получите:

RuntimeError: 
        An attempt has been made to start a new process before the
        current process has finished its bootstrapping phase.

        This probably means that you are not using fork to start your
        child processes and you have forgotten to use the proper idiom
        in the main module:

            if __name__ == '__main__':
                freeze_support()
                ...

        The "freeze_support()" line can be omitted if the program
        is not going to be frozen to produce an executable.

Вы также можете использовать spawn в операционных системах POSIX, чтобы имитировать поведение, которое вы видели в Windows:

import random
import os
from multiprocessing import Process, set_start_method
import platform

num = random.randint(0, 100)

def show_num():
    print("pid:{}, num is {}".format(os.getpid(), num))

if __name__ == '__main__':
    print(platform.system())
    # change the start method for new processes to spawn
    set_start_method("spawn")
    print("pid:{}, num is {}".format(os.getpid(), num))
    p = Process(target=show_num)
    p.start()
    p.join()
    print('Parent Process Stop')

Выход:

Linux
pid:26835, num is 41
pid:26839, num is 13
Parent Process Stop
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...