如何在Windows上等待Python中的多个subprocess,而无需等待(轮询)? 像这样的东西几乎适用于我:
proc1 = subprocess.Popen(['python','mytest.py']) proc2 = subprocess.Popen(['python','mytest.py']) proc1.wait() print "1 finished" proc2.wait() print "2 finished"
问题是,当proc2
在proc1
之前完成时,父进程将仍然等待proc1
。 在Unix上,在循环中使用waitpid(0)
来获得subprocess的返回代码 – 如何在Windows上的Python中实现这样的function?
看起来似乎有点过分,但是,在这里呢?
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
Twisted有一个在Windows上运行的异步进程生成API 。 实际上有几种不同的实现方式,其中许多不是很好,但是你可以在不改变代码的情况下在它们之间切换。
基于zseil的答案,你可以用子进程和win32 API调用的混合来实现。 我使用了直接的ctypes,因为我的Python没有安装win32api。 我只是从MSYS产生sleep.exe作为例子,但显然你可以产生你喜欢的任何进程。 我使用OpenProcess()从进程PID中获取HANDLE,然后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!"
在Windows上扭曲将执行一个积极的等待下封面。 如果你不想使用线程,你将不得不使用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)
你可以使用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)