Что такое модуль многопроцессорности Python.join() Doing?
Изучение Python Multiprocessing (из статья PMOTW), и мне хотелось бы получить некоторое разъяснение о том, что именно делает метод join()
.
В старом учебнике с 2008 года говорится, что без вызова p.join()
в приведенном ниже коде "дочерний процесс будет простаивать и не заканчивается, становясь зомби, вы должны убить вручную".
from multiprocessing import Process
def say_hello(name='world'):
print "Hello, %s" % name
p = Process(target=say_hello)
p.start()
p.join()
Я добавил распечатку PID
, а также time.sleep
для проверки, и, насколько я могу судить, процесс завершается самостоятельно:
from multiprocessing import Process
import sys
import time
def say_hello(name='world'):
print "Hello, %s" % name
print 'Starting:', p.name, p.pid
sys.stdout.flush()
print 'Exiting :', p.name, p.pid
sys.stdout.flush()
time.sleep(20)
p = Process(target=say_hello)
p.start()
# no p.join()
в течение 20 секунд:
936 ttys000 0:00.05 /Library/Frameworks/Python.framework/Versions/2.7/Reso
938 ttys000 0:00.00 /Library/Frameworks/Python.framework/Versions/2.7/Reso
947 ttys001 0:00.13 -bash
через 20 секунд:
947 ttys001 0:00.13 -bash
Поведение одинаково с p.join()
, добавленным в конце файла. Модуль Python недели предлагает очень читаемое объяснение модуля; "Чтобы дождаться завершения процесса и выхода из него, используйте метод join()., Но похоже, что по крайней мере OS X все равно это делала.
Мне также интересно узнать имя метода. Является ли метод .join()
конкатенированием чего-либо здесь? Это конкатенирование процесса с его завершением? Или просто передайте имя с помощью собственного метода .join()
на языке Python?
Ответы
Ответ 1
Метод join()
, когда он используется с threading
или multiprocessing
, не связан с str.join()
- он фактически не объединяет ничего вместе. Скорее, это просто означает "дождитесь завершения этого [потока/процесса]". Имя join
используется, потому что API модуля multiprocessing
должен выглядеть похожим на API модуля threading
, а модуль threading
использует join
для своего объекта Thread
. Использование термина join
для обозначения "ожидание завершения потока" является общим для многих языков программирования, поэтому Python просто принял его также.
Теперь причина, по которой вы видите 20-секундную задержку как с вызовом join()
, так и без него, заключается в том, что по умолчанию, когда основной процесс готов к завершению, он будет неявно вызывать join()
для всех запущенных multiprocessing.Process
экземпляров. Это не так четко указано в документах multiprocessing
, как и должно быть, но оно упоминается в разделе Руководства по программированию:
Помните также, что не-демонические процессы будут автоматически присоединился.
Вы можете переопределить это поведение, установив флаг daemon
на Process
до True
до запуска процесса:
p = Process(target=say_hello)
p.daemon = True
p.start()
# Both parent and child will exit here, since the main process has completed.
Если вы это сделаете, дочерний процесс будет завершен, как только основной процесс завершится:
демон
Флаг демона процессов, логическое значение. Это необходимо установить перед Вызывается start().
Начальное значение наследуется от процесса создания.
Когда процесс завершается, он пытается завершить все свои демонические дочерние процессы.
Ответ 2
Без join()
основной процесс может завершиться до того, как будет выполняться дочерний процесс. Я не уверен, при каких обстоятельствах это приводит к зомбизму.
Основной целью join()
является обеспечение того, чтобы дочерний процесс завершился до того, как основной процесс выполнит все, что зависит от работы дочернего процесса.
Этимология join()
заключается в том, что она противоположна fork
, что является общим термином в операционных системах семейства Unix для создания дочерних процессов. Один процесс "вилки" в несколько, затем "присоединяется" обратно к одному.
Ответ 3
Я не буду подробно объяснять, что делает join
, но здесь этимология и интуиция за ней, что должно помочь вам легче запомнить ее смысл.
Идея заключается в том, что выполнение вилок "в несколько процессов, одним из которых является мастер, остальные работники (или" подчиненные "). Когда рабочие завершены, они" присоединяются" к мастеру, чтобы серийное исполнение могло быть возобновлено.
Метод join
заставляет мастер-процесс ждать, пока работник присоединится к нему. Метод можно было бы лучше назвать "ждать", так как это фактическое поведение, которое он вызывает в master (и то, что он вызвал в POSIX, хотя потоки POSIX также называют его "join" ). Присоединение происходит только как эффект взаимодействующих потоков, это не то, что делает мастер.
Имена "fork" и "join" использовались с этим значением при многопроцессорной обработке с 1963 года.