2015-01-12 3 views
0

Я запускаю несколько подпроцессов параллельно, но мне нужно заблокировать каждый процесс, пока подпроцесс не даст результат (через функцию печати). В подпроцессах выполняется сценарий python, который был упакован в исполняемый файл.Заблокировать процесс до тех пор, пока подпроцесс не достигнет определенной точки

код выглядит следующим образом:

import multiprocessing as mp 
import subprocess 
import os 


def main(args): 

    l,inpath = args 
    l.acquire() 
    print "Running KNN.exe for files in %s" % os.path.normpath(inpath).split('\\')[-1] 

    #Run KNN executable as a subprocess 
    subprocess.call(os.path.join(os.getcwd(), "KNN.exe")) 
    #This is where I want to wait for any output from the subprocess before releasing the lock 
    l.release() 

    #Here I would like to wait until subprocess is done then print that it is done 
    l.acquire() 
    print "Done %s" % os.path.normpath(inpath).split('\\')[-1] 
    l.release() 


if __name__ == "__main__": 
    #Set working directory path containing input text file 
    os.chdir("C:\Users\Patrick\Google Drive\KNN") 
    #Get folder names in directory containing GCM input 
    manager = mp.Manager() 
    l = manager.Lock() 
    gcm_dir = "F:\FIDS_GCM_Data_CMIP5\UTRB\UTRB KNN-CAD\Input" 
    paths = [(l, os.path.join(gcm_dir, folder)) for folder in os.listdir(gcm_dir)]  
    #Set up multiprocessing pool 
    p = mp.Pool(mp.cpu_count()) 
    #Map function through input paths 
    p.map(main, paths) 

Поэтому цель состоит в том, чтобы зафиксировать процесс так, чтобы подпроцесс не может быть запущен до получения выходного сигнала. После этого блокировка может быть освобождена, и подпроцесс может продолжаться, пока он не будет завершен, тогда я бы хотел напечатать, что он завершен.

Мой вопрос в том, как я могу подождать одиночный (и только) выход из подпроцесса, прежде чем освободить блокировку процесса (из нескольких)?

Кроме того, как я могу дождаться завершения процесса, а затем распечатать его, чтобы завершить?

ответ

2

Ваш код использует метод call, который уже ожидает завершения подпроцесса (что означает, что все выходные данные уже сгенерированы). Я выхожу из вашего вопроса, который вы хотели бы различать, когда вывод сначала написан и когда подпроцесс завершен. Ниже код с моей рекомендуемой модификацией встраиваемым:

def main(args): 

    l,inpath = args 
    l.acquire() 
    print "Running KNN.exe for files in %s" % os.path.normpath(inpath).split('\\')[-1] 

    #Run KNN executable as a subprocess 
    #Use the Popen constructor 
    proc = subprocess.Popen(os.path.join(os.getcwd(), "KNN.exe"), stdout=subprocess.PIPE) 

    #This is where I want to wait for any output from the subprocess before releasing the lock 
    # Wait until the subprocess has written at least 1 byte to STDOUT (modify if you need different logic) 
    proc.stdout.read(1) 

    l.release() 

    #Here I would like to wait until subprocess is done then print that it is done 
    #proc.wait() 
    (proc_output, proc_error) = proc.communicate() 

    l.acquire() 
    print "Done %s" % os.path.normpath(inpath).split('\\')[-1] 
    l.release() 

Обратите внимание, что выше, не предполагает, что вы хотите сделать что-нибудь с выходом подпроцесса в другом, чем проверить, что он был сформирован. Если вы хотите сделать что-либо с этим выходом, который будет менее тривиальным, чем предыдущий (потребляйте 1 байт, а затем опустите его на пол), то proc.stdout (являющийся объектом file) должен представлять все, что генерируется подпроцессом во время работы.

+0

Ah хорошо, отлично! Да, различие между первым выходом подпроцесса и его окончанием - это именно то, что я имел в виду. В этом случае мне нужен только первый вывод, но я думаю, что 'proc.stdout' будет полезен в будущем. – pbreach

+0

@ user2593236 Я рад, если это помогло. Чтобы снова подчеркнуть предостережение в моем ответе, этот первый байт отбрасывается, если результат 'proc.stdout.read (1)' не получает никакого привязки к чему-либо. Так что это прекрасно, если «нужен первый вывод» означает, что вы не имеете в виду «нужно знать, что такое первый выходной байт». :) – rchang

+2

@pbreach: код, написанный в ответе, может зайти в тупик, если дочерний процесс генерирует достаточное количество выходных данных (по крайней мере, в Unix, я не знаю, могут ли буферы труб расти на Windows неограниченно). Вы должны прочитать результат, например, 'deque (p.stdout, maxlen = 0); p.stdout.close(); p.wait() ', чтобы отбросить его после чтения первого байта или' out, err = p.communicate() 'для захвата вывода в строке. – jfs

Смежные вопросы