Python/Windows/ctypes: How to get process return status after calling WaitForMultipleObjects?
我和这个人有相同的用例,我真的很喜欢这个答案,除了我有一个额外的要求:我需要从子进程中获取返回状态。
这是我尝试修改他的程序的尝试。我是Windows-land和Python ctypes的旅行者,所以希望我没有做任何愚蠢的事情...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | import ctypes, subprocess from random import randint import os SYNCHRONIZE=0x00100000 PROCESS_QUERY_INFORMATION=0x0400 INFINITE = -1 numprocs = 5 handles = {} class Err(BaseException): pass for i in xrange(numprocs): sleeptime = randint(5,10) p = subprocess.Popen([r"c:\\MinGW\\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 | PROCESS_QUERY_INFORMATION, 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] print"Process %d done" % handles[h] i = ctypes.c_int(0) pi = ctypes.pointer(i) if ctypes.windll.kernel32.GetExitCodeProcess(h, pi) == 0: err = ctypes.windll.kernel32.GetLastError() raise Err("GetExitCodeProcess: %d" % (err)) print"Status code is: %d" % (i) if ctypes.windll.kernel32.CloseHandle(h) == 0: err = ctypes.windll.kernel32.GetLastError() raise Err("CloseHandle: %d" % (err)) del handles[h] print"All done! |
但是当我运行它时,我失败了:
1 2 3 4 | Traceback (most recent call last): File"test.py", line 30, in <module> raise Err("GetExitCodeProcess: %d" % (err)) __main__.Err: GetExitCodeProcess: 6 |
似乎错误6是ERROR_INVALID_HANDLE。但是我不确定为什么手柄无效。我请求了
有什么想法吗?等待一堆进程后如何获取状态码?
使用此确切的Python代码(与您相同的只是一些缩进已修复,并删除了sleep.exe的路径):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | import ctypes, subprocess from random import randint import os SYNCHRONIZE=0x00100000 PROCESS_QUERY_INFORMATION=0x0400 INFINITE = -1 numprocs = 5 handles = {} class Err(BaseException): pass for i in xrange(numprocs): sleeptime = randint(5,10) p = subprocess.Popen([r"sleep.exe", str(sleeptime)], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False) h = ctypes.windll.kernel32.OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION, 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] print"Process %d done" % handles[h] i = ctypes.c_int(0) pi = ctypes.pointer(i) if ctypes.windll.kernel32.GetExitCodeProcess(h, pi) == 0: err = ctypes.windll.kernel32.GetLastError() raise Err("GetExitCodeProcess: %d" % (err)) print"Status code is: %d" % i.value if ctypes.windll.kernel32.CloseHandle(h) == 0: err = ctypes.windll.kernel32.GetLastError() raise Err("CloseHandle: %d" % (err)) del handles[h] print"All done!" |
给出以下输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | C:\\tmp\\pyt>python -V Python 2.7.3 C:\\tmp\\pyt>python a.py Spawned Process 4368 Spawned Process 268 Spawned Process 5792 Spawned Process 4744 Spawned Process 4484 Waiting for 5 children... Process 5792 done Status code is: 0 Waiting for 4 children... Process 4484 done Status code is: 0 Waiting for 3 children... Process 268 done Status code is: 0 Waiting for 2 children... Process 4368 done Status code is: 0 Waiting for 1 children... Process 4744 done Status code is: 0 All done! |
因此它似乎正在工作。您的问题不是在其他地方吗?您正在使用什么操作系统(Vista是我的操作系统)?您是否拥有最新版本的Python(2.7.3)?您的\\" sleep.exe \\"是否以某种方式损坏了?您是否尝试了其他命令?