2008-09-19 3 views
21

활성 대기 (폴링)없이 Windows의 Python에서 여러 하위 프로세스를 대기하는 방법은 무엇입니까? 나를 위해이 거의 작품처럼 뭔가 :Windows의 Python - 여러 자식 프로세스를 대기하는 방법?

proc1 = subprocess.Popen(['python','mytest.py']) 
proc2 = subprocess.Popen(['python','mytest.py'])  
proc1.wait() 
print "1 finished" 
proc2.wait() 
print "2 finished" 

문제 proc1 전에 proc2 완료는, 부모 프로세스가 계속 proc1 기다릴 때이다. 유닉스에서 루프에서 waitpid(0)을 사용하면 자식 프로세스의 리턴 코드를 얻을 수 있습니다 - Windows의 Python에서 이와 같은 것을 어떻게 달성 할 수 있습니까?

+0

당신은 waitpid를 (0) 유닉스에서 사용하는 것을 설명 할 수 있습니다

선택적으로 당신은 감시 프로세스 중 하나가 종료 될 때마다 호출됩니다 콜백을 지정할 수 있습니다? –

+2

http://docs.python.org/library/os.html#os.waitpid 유닉스에서'waitpid (0)'은 사용 가능한 자식 상태에 대해 대기하고 ('WNOHANG'이 옵션에없는 경우) 기다리고'(, 상태)'튜플. –

답변

13

여기 간다, 과잉 보이지만, 수 있습니다

import Queue, thread, subprocess 

results= Queue.Queue() 
def process_waiter(popen, description, que): 
    try: popen.wait() 
    finally: que.put((description, popen.returncode)) 
process_count= 0 

proc1= subprocess.Popen(['python', 'mytest.py']) 
thread.start_new_thread(process_waiter, 
    (proc1, "1 finished", results)) 
process_count+= 1 

proc2= subprocess.Popen(['python', 'mytest.py']) 
thread.start_new_thread(process_waiter, 
    (proc2, "2 finished", results)) 
process_count+= 1 

# etc 

while process_count > 0: 
    description, rc= results.get() 
    print "job", description, "ended with rc =", rc 
    process_count-= 1 
+0

글쎄, 호출이 병렬 처리를 지원하지 않는다면 외부로 구현해야합니다 :-) 감사합니다! –

+2

예제 스크립트에 사소한 오류가 있다고 생각합니다. 어떤 종류의 명령문도 보이지 않습니다. process_count - = 1 마지막 "while"무한 루프가 아닙니까? –

+0

@Ricardo Reyes : 예, 복사 붙여 넣기가 완료되지 않았습니다. 고맙습니다. – tzot

5

트위스트 Windows에서 작동하는 asynchronous process-spawning API 있습니다. 실제로는 여러 가지 구현이 있습니다. 그 중 많은 부분은 그리 훌륭하지 않지만 코드를 변경하지 않고도 전환 할 수 있습니다.

4

Windows에서 Twisted하면 커버 아래에서 활성 대기가 수행됩니다. 스레드를 사용하지 않으려면, win32 API를 사용하여 폴링을 피하십시오. 이런 식으로 :

import win32process 
import win32event 

# Note: CreateProcess() args are somewhat cryptic, look them up on MSDN 
proc1, thread1, pid1, tid1 = win32process.CreateProcess(...) 
proc2, thread2, pid2, tid2 = win32process.CreateProcess(...) 
thread1.close() 
thread2.close() 

processes = {proc1: "proc1", proc2: "proc2"} 

while processes: 
    handles = processes.keys() 
    # Note: WaitForMultipleObjects() supports at most 64 processes at a time 
    index = win32event.WaitForMultipleObjects(handles, False, win32event.INFINITE) 
    finished = handles[index] 
    exitcode = win32process.GetExitCodeProcess(finished) 
    procname = processes.pop(finished) 
    finished.close() 
    print "Subprocess %s finished with exit code %d" % (procname, exitcode) 
+0

활성 대기를 수행하는 스레드 솔루션에 대해 틀렸어. 나는 Twisted에 관해 모른다. –

5

zseil의 답변을 바탕으로 작성하면 하위 프로세스와 win32 API 호출을 혼합하여이 작업을 수행 할 수 있습니다. 필자는 파이썬이 win32api를 설치하지 않았기 때문에 직선의 ctypes를 사용했습니다. 난 그냥 여기에 예를 들어, MSYS에서 sleep.exe를 산란거야하지만 분명히 당신이 좋아하는 모든 프로세스를 산란 수 있습니다. OpenProcess()를 사용하여 프로세스의 PID에서 핸들을 가져온 다음 WaitForMultipleObjects를 사용하여 프로세스가 완료 될 때까지 기다립니다.

import ctypes, subprocess 
from random import randint 
SYNCHRONIZE=0x00100000 
INFINITE = -1 
numprocs = 5 
handles = {} 

for i in xrange(numprocs): 
    sleeptime = randint(5,10) 
    p = subprocess.Popen([r"c:\msys\1.0\bin\sleep.exe", str(sleeptime)], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False) 
    h = ctypes.windll.kernel32.OpenProcess(SYNCHRONIZE, False, p.pid) 
    handles[h] = p.pid 
    print "Spawned Process %d" % p.pid 

while len(handles) > 0: 
    print "Waiting for %d children..." % len(handles) 
    arrtype = ctypes.c_long * len(handles) 
    handle_array = arrtype(*handles.keys()) 
    ret = ctypes.windll.kernel32.WaitForMultipleObjects(len(handle_array), handle_array, False, INFINITE) 
    h = handle_array[ret] 
    ctypes.windll.kernel32.CloseHandle(h) 
    print "Process %d done" % handles[h] 
    del handles[h] 
print "All done!" 
2

당신은 psutil를 사용할 수 있습니다

>>> import subprocess 
>>> import psutil 
>>> 
>>> proc1 = subprocess.Popen(['python','mytest.py']) 
>>> proc2 = subprocess.Popen(['python','mytest.py'])  
>>> ls = [psutil.Process(proc1.pid), psutil.Process(proc2.pid)] 
>>> 
>>> gone, alive = psutil.wait_procs(ls, timeout=3) 

'사라'와 '생존'이다 프로세스가 사라하고있는 사람이 아직 살아 있는지를 나타내는리스트.

>>> def on_terminate(proc): 
...  print "%s terminated" % proc 
... 
>>> gone, alive = psutil.wait_procs(ls, timeout=3, callback=on_terminate)