2008-10-06 7 views
8

Сценарий python должен порождать несколько подпроцессов через fork(). Все эти дочерние процессы должны выполняться одновременно, и родительский процесс должен ждать завершения всех этих процессов. Было бы неплохо иметь возможность установить некоторый тайм-аут на «медленном» ребенке. Родительский процесс обрабатывает остальную часть скрипта после того, как все дети собраны.Каков наилучший способ запуска нескольких подпроцессов через fork()?

Каков наилучший способ его решения? Благодарю.

ответ

10

Простой пример:

import os 
chidren = [] 
for job in jobs: 
    child = os.fork() 
    if child: 
     children.append(child) 
    else: 
     pass # really should exec the job 
for child in children: 
    os.waitpid(child, 0) 

таймаут медленный ребенок немного больше работы; вы можете использовать wait вместо waitpid и отбирать возвращаемые значения из списка детей, а не ждать по очереди (как здесь). Если вы настроили alarm с обработчиком SIGALRM, вы можете завершить ожидание после указанной задержки. Это все стандартные файлы UNIX, а не Python-специфические ...

+0

Должен ли дочерний процесс выйти после выполнения? – zuo 2013-11-06 03:54:41

+0

@zuo Ребенок должен выполнить `exec` (заменяя его дочерним элементом для запуска) или` _exit`. – ephemient 2013-11-06 05:59:46

1

Традиционный способ UNIX-y для связи с подпроцессами заключается в том, чтобы открыть каналы на их стандартный ввод/вывод и использовать системный вызов select() для мультиплексирования сообщений в родительском процессе (доступно в Python через ... модуль select).

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

4

Ephemient: каждый ребенок в вашем коде останется в цикле for после его окончания работы. Он будет вилка снова и снова. Более того, дети, которые начинают, когда дети [] не пусты, будут пытаться дождаться некоторых своих братьев в конце цикла. В конце концов кто-то рухнет. Обходным путем является:

import os, time 

def doTheJob(job): 
    for i in xrange(10): 
     print job, i 
     time.sleep(0.01*ord(os.urandom(1))) 
     # random.random() would be the same for each process 

jobs = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J"] 
imTheFather = True 
children = [] 

for job in jobs: 
    child = os.fork() 
    if child: 
     children.append(child) 
    else: 
     imTheFather = False 
     doTheJob(job) 
     break 

# in the meanwhile 
# ps aux|grep python|grep -v grep|wc -l == 11 == 10 children + the father 

if imTheFather: 
    for child in children: 
     os.waitpid(child, 0) 
Смежные вопросы