python – subprocess.popen()使用管道/失败的stderr重定向
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了python – subprocess.popen()使用管道/失败的stderr重定向,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含2431字,纯文字阅读大概需要4分钟。
内容图文
我想运行一个进程,它可以产生大量输出,最多超时秒,捕获stdout / stderr.根据documentation for subprocess,使用capture()和PIPE作为stdout / 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)
但是,如果进程被内核(内存不足等)杀死,即使这样也无法捕获错误.
什么是这个问题的理想解决方案?
解决方法:
不使用文件作为输出,而是返回使用管道,但使用fcntl模块将p.stdout和p.stder变为非阻塞模式.这将导致p.stdout.read()和p.stderr.read()返回任何可用数据,或者如果没有数据则引发IOError,而不是阻塞:
import fcntl, os
p = subprocess.Popen(args = exe,
stdout = subprocess.PIPE,
stderr = subprocess.PIPE,
cwd = dir)
fcntl.fcntl(p.stdout.fileno(), fcntl.F_SETFL, os.O_NONBLOCK)
fcntl.fcntl(p.stderr.fileno(), fcntl.F_SETFL, os.O_NONBLOCK)
outdata, errdata = '', ''
while p.poll() is None:
try:
outdata += p.stdout.read()
except IOError:
pass
try:
errdata += p.stderr.read()
except IOError:
pass
time.sleep(sleepDuration)
正如glglgl在注释中指出的那样,你应该在except IOError子句中做一些额外的检查,以确保它实际上不是真正的错误.
内容总结
以上是互联网集市为您收集整理的python – subprocess.popen()使用管道/失败的stderr重定向全部内容,希望文章能够帮你解决python – subprocess.popen()使用管道/失败的stderr重定向所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。