我想運行一個進程,可能會產生大量的輸出達到超時秒數,捕獲stdout
/stderr
。根據documentation for subprocess
,使用capture()
和PIPE
作爲stdout
/stderr
容易發生死鎖。subprocess.popen()stderr重定向與管道/失敗
現在,我使用poll()
反正 - 因爲我希望能夠在超時後終止進程 - 但我仍然不知道如何使用PIPE避免死鎖。我怎麼做?
目前我只是通過創建臨時文件工作圍繞:
#because of the shitty api, this has to be a file, because std.PIPE is prone to deadlocking with a lot of output, and I can't figure out what to do about it
out, outfile = tempfile.mkstemp()
err, errfile = tempfile.mkstemp()
now = datetime.datetime.now().strftime('%H:%M, %Ss')
print "Running '" + exe + "' with a timeout of ", timeout , "s., starting at ", now
p = subprocess.Popen(args = exe,
stdout = out,
#for some reason, err isn't working if the process is killed by the kernel for, say, using too much memory.
stderr = err,
cwd = dir)
start = time.time()
# take care of infinite loops
sleepDuration = 0.25
time.sleep(0.1)
lastPrintedDuration = 0
duration = 0
while p.poll() is None:
duration = time.time() - start
if duration > lastPrintedDuration + 1:
lastPrintedDuration += 1
#print '.',
sys.stdout.flush()
if duration >= timeout:
p.kill()
raise Exception("Killed after " + str(duration) + "s.")
time.sleep(sleepDuration)
if p.returncode is not 0:
with open(errfile, 'r') as f:
e = f.read()
#fix empty error messages
if e == '':
e = 'Program crashed, or was killed by kernel.'
f.close()
os.close(out)
os.close(err)
os.unlink(outfile)
os.unlink(errfile)
print "Error after " + str(duration) + 's: ',
print "'" + e + "'"
raw_input('test')
raise Exception(e)
else:
print "completed in " + str(duration) + 's.'
os.close(out)
os.close(err)
os.unlink(outfile)
os.unlink(errfile)
但是,即使這未能捕捉到錯誤如果進程,比方說打死,內核(內存等) 。
這個問題的理想解決方案是什麼?
+1閱讀文檔。 – 2012-02-06 18:48:02