Разница, объясняющая поведение, описанное в вашем посте, именно то, что вы упомянули: метод запуска , используемый для создания процесса. В ОС 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