像这样的东西?
注意这个 flush()
问题,这里没有使用 PIPE;在 Windows 下使用 python 2.7.1 对我有用。
import os
import subprocess
import sys
import time
g_WINDOWS = os.name == 'nt'
g_LINUX = os.name == 'posix'
def startProcess(sArgs, dTimeOut = 0.0, hOut = sys.stdout):
""" Starts process \emph sArgs (command and paramters seperated by spaces).
If \emph dTimeOut > 0, starts subprocess and if that does not end earlier, kills process after \emph dTimeOut (>0) seconds.
If \emph dTimeOut = 0, waits until subprocess terminates (unlimited).
If \emph dTimeOut < 0, starts subprocess and returns leaving it running separately.
Redirects stdout and stderr to open file handle \emph hOut.
If (dTimeOut <= 0) returns 0 else
returns return code of started process.
\empth hOut: writing and re-reading of a file needed, if printing to console AND to file wished
"""
try : hOut.flush() # at least under Windows partly needed to avoid mixed outputs
except: pass
p = subprocess.Popen(sArgs, stdin=None, stdout = hOut, stderr = hOut, preexec_fn=None, close_fds=False)
i = 0
if dTimeOut > 0:
tSleep = dTimeOut / 25.0
# timeout for subprocess given
tStart = time.clock()
while 1:
# poll subprocess
retVal_p = p.poll()
if retVal_p != None: # terminated?
# ----------------------
p.communicate() # if PIPE: get output when done, no interface to get it chunk-wise
# ----------------------
break
# check timout
if (time.clock() - tStart) > dTimeOut:
if g_WINDOWS: killCmd = "taskkill.exe /PID %d /F" % p.pid
elif g_LINUX: killCmd = "kill -KILL %d" % p.pid
pKill = subprocess.Popen(killCmd, stdout = hOut, stderr = hOut)
while 1:
retVal_pKill = pKill.poll()
time.sleep(1)
if retVal_pKill != None:
break
break
time.sleep(tSleep)
elif dTimeOut < 0:
# let subprocess run alone
return 0
else:
# wait until subprocess terminates (no timeout)
p.communicate()
try : hOut.flush() # at least under Windows partly needed to avoid mixed outputs
except: pass
return p.returncode
if __name__ == "__main__":
#-----------------------------------
## just console
print 'startProcess("echo foo "):', startProcess("echo foo ") # stdout, ret 0
print 'startProcess("rmdir BBB"):', startProcess("rmdir BBB") # stderr, ret 1
print
sys.stdout.flush() # at least under Windows partly needed to avoid mixed outputs
#-----------------------------------
# same with logging to file
fnLog = "my_test.log"
f = file(fnLog, "w")
f.write("v"*80 + " before\n")
print 'startProcess("rmdir BBB", hOut=f):', startProcess("rmdir BBB", hOut=f) # stdout, ret 0
print 'startProcess("echo foo ", hOut=f):', startProcess("echo foo ", hOut=f) # stderr, ret 1
sys.stdout.flush() # at least under Windows partly needed to avoid mixed outputs
f.write("^"*80 + " after\n")
f.close()
f = open(fnLog, "r")
s_log = f.read()
f.close();
print "%s:" % (fnLog)
print s_log
#-----------------------------------
#clean up
os.unlink(fnLog)