0

私はこの男と同じユースケースを持っています.1つの追加要件があることを除いて、この答えが本当に気に入っています.子プロセスから戻りステータスを取得する必要があります.

これが彼のプログラムを変更する私の試みです。私は Windows ランドと Python ctypes の観光客なので、ばかげたことはしていないことを願っています...

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!

しかし、これを実行すると失敗します。

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のようです。しかし、ハンドルが無効な理由はわかりません。PROCESS_QUERY_INFORMATION私は許可を求めましたが、CloseHandle()呼び出しをコメントアウトすると、呼び出しは正常に機能しGetExitCodeProcess()ます。

何か案は?一連のプロセスを待った後、ステータス コードを取得するにはどうすればよいですか?

4

1 に答える 1

1

この正確なPythonコードを使用します(あなたのものと同じですが、いくつかのインデントが修正され、sleep.exeへのパスが削除されました):

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!"

この出力が得られます:

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!

だからそれは働いているようです。あなたの問題は、まったく別の場所にあるのではないですか? 使用しているOSは何ですか(私はVistaです)?最新バージョンの Python (2.7.3) を使用していますか? 「sleep.exe」が壊れていませんか?別のコマンドを試しましたか?

于 2012-05-02T10:12:46.847 に答える