Попытка понять многопроцессорность с основным в Python - PullRequest
3 голосов
/ 25 марта 2012

Используя код ниже, я получаю странный вывод:

import  sys 
from  multiprocessing import Process
import time
from time import strftime

now =time.time()    
print time.strftime("%Y%m%d %H:%M:%S", time.localtime(now)) 

fr= [1,2,3]
for row in fr:
    print 3

print 1

def worker():
    print 'worker line'
    time.sleep(1)
    sys.exit(1)

def main():
    print 'start worker'
    Process(target=worker, args=()).start()
    print 'main line'

if __name__ == "__main__":
    start_time = time.time()
    main()
    end_time = time.time()
    duration = end_time - start_time
    print "Duration: %s" % duration

Вывод:

20120324 20:35:53
3
3
3
1
start worker
main line
Duration: 0.0
20120324 20:35:53
3
3
3
1
worker line 

Я думал, что получу это:

20120324 20:35:53
3
3
3
1
start worker
worker line
main line
Duration: 1.0

Почему этот прогон дважды?Использование python 2.7 в WinX64:

20120324 20:35:53
3
3
3
1
worker line 

Ответы [ 2 ]

5 голосов
/ 25 марта 2012

проблема в основном потому, что multiprocessing действительно предназначен для работы в системе posix, с системным вызовом fork(2).в этих операционных системах процесс может быть разделен на две части: дочерний процесс магически клонирует состояние от родительского элемента, и оба возобновляют работу в одном и том же месте, и у дочернего элемента теперь появляется новый идентификатор процесса.В этой ситуации multiprocessing может организовать некоторый механизм для передачи состояния от родителя к потомку по мере необходимости, с уверенностью, что у потомка уже будет большая часть необходимого состояния питона.

Windows не имеет fork().

И поэтому multiprocessing должен поднять слабину.Это в основном включает запуск нового интерпретатора Python, выполняющего многопроцессорный дочерний скрипт.Почти сразу родитель попросит ребенка использовать что-то, находящееся в состоянии родителя, и поэтому ребенку придется воссоздать это состояние с нуля, , импортировав свой сценарий в дочернее устройство .

Таким образом, все, что происходит во время импорта в вашем скрипте, будет происходить дважды, один раз в родительском и снова в дочернем, поскольку это воссоздает среду питона, необходимую для обслуживания родителя.

0 голосов
/ 25 марта 2012

Это то, что я получаю, когда запускаю ваш код в Linux с использованием Python 2.7.3:

20120324 23:05:49
3
3
3
1
start worker
main line
Duration: 0.0045280456543
worker line

Я не знаю, почему ваш запускается дважды, но я могу вам сказать, почему он невернуть ожидаемое время или распечатать в «правильном» порядке.

Когда вы запускаете процесс с использованием multiprocessing, запуск выполняется асинхронно.Таким образом, функция .start() немедленно возвращается в родительский процесс, так что родительский процесс может продолжать работать и выполнять другие действия (например, запускать больше процессов), пока дочерний процесс выполняет свою собственную работу в фоновом режиме.Если вы хотите заблокировать выполнение родительского процесса до завершения дочернего процесса, вам следует использовать функцию .join().Вот так:

def main():
    print 'start worker'
    p = Process(target=worker, args=())
    p.start()
    p.join()
    print 'main line'
...