Windows上的Python - 如何等待多个子进程?

Raf*_*ird 21 python windows asynchronous

如何在Windows上等待Python中的多个子进程,没有主动等待(轮询)?这样的东西几乎适合我:

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

问题是,在proc2完成之前proc1,父进程仍将等待proc1.在Unix上,人们会waitpid(0)在循环中使用它来完成子进程的返回代码 - 如何在Windows上用Python实现类似的东西?

tzo*_*zot 14

这似乎有点矫枉过正,但是,这里有:

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
Run Code Online (Sandbox Code Playgroud)

  • 如果你使用的是 Python 3,`Queue` 模块被重命名为 `queue`,`thread` 模块被重命名为 `_thread`。 (4认同)
  • 现在还不是圣诞节,但我的愿望是让 Python 添加一个新的 waitForMultiple 函数,该函数可以保护用户免受所有这些低级内容的影响,并且无论我们使用的是 Linux 还是 Windows,它都能正常工作。:) (3认同)

Gly*_*yph 5

Twisted有一个异步的进程生成API,适用于Windows.实际上有几种不同的实现,其中许多并不是很好,但您可以在不更改代码的情况下在它们之间切换.


Ted*_*rek 5

基于zseil的答案,您可以通过混合使用subprocess和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!"
Run Code Online (Sandbox Code Playgroud)