这就是我想要实现的目标
def fun():
runner = InteractiveConsole()
while(True):
code = raw_input()
code.rstrip('\n')
# I want to achieve the following
# By default the output and error of the 'code' is sent to STDOUT and STDERR
# I want to obtain the output in two variables out and err
out,err = runner.push(code)
到目前为止我所看到的所有解决方案都使用任一管道来发出单独的脚本执行命令(在我的情况下这是不可能的)。我可以通过其他任何方式实现这一目标吗?
答案 0 :(得分:6)
import StringIO, sys
from contextlib import contextmanager
@contextmanager
def redirected(out=sys.stdout, err=sys.stderr):
saved = sys.stdout, sys.stderr
sys.stdout, sys.stderr = out, err
try:
yield
finally:
sys.stdout, sys.stderr = saved
def fun():
runner = InteractiveConsole()
while True:
out = StringIO.StringIO()
err = StringIO.StringIO()
with redirected(out=out, err=err):
out.flush()
err.flush()
code = raw_input()
code.rstrip('\n')
# I want to achieve the following
# By default the output and error of the 'code' is sent to STDOUT and STDERR
# I want to obtain the output in two variables out and err
runner.push(code)
output = out.getvalue()
print output
在较新版本的python中,此上下文管理器内置于:
with contextlib.redirect_stdout(out), contextlib.redirect_stderr(err):
...
答案 1 :(得分:1)
InteractiveConsole没有公开用于设置输出或错误的对象等文件的API,您需要monkey patch sys.stdout
和sys.stderr
。与猴子修补一样,要注意副作用可能是什么。在这种情况下,您将使用自己的实现替换全局stdin和stdout文件对象,这可能会吞噬非预期的输出(特别是如果您使用任何线程)。
使用类似的东西来“输出”输出会更安全一些:
import sys
import StringIO
class TeeBuffer(object):
def __init__(self, real):
self.real = real
self.buf = StringIO.StringIO()
def write(self, val):
self.real.write(val)
self.buf.write(val)
def fun():
runner = InteractiveConsole()
out = TeeBuffer(sys.stdout)
err = TeeBuffer(sys.stderr)
sys.stdout = out
sys.stderr = err
while(True):
code = raw_input()
code.rstrip('\n')
out, err = runner.push(code)
outstr = out.buf.getvalue()
errstr = err.buf.getvalue()
sys.stdout = out.real
sys.stderr = err.real
然后您的用户仍然可以看到输出,而无需担心每次运行时将其打印回正确的位置。
答案 2 :(得分:0)
您可以使用上下文管理器redirect stdout temporarily:
@contextmanager def stdout_redirected(new_stdout): save_stdout = sys.stdout sys.stdout = new_stdout try: yield None finally: sys.stdout = save_stdout
使用如下:
with opened(filename, "w") as f: with stdout_redirected(f): print "Hello world"
当然,这不是线程安全的,但也没有手动进行同样的舞蹈。在单线程程序中(例如,在脚本中),它是一种流行的做事方式。
可以轻松调整此选项,将stdout
和stderr
重定向到cStringIO
:
@contextmanager
def out_redirected():
save_stdout = sys.stdout
save_stderr = sys.stderr
sys.stdout = cStringIO.String()
sys.stderr = cStringIO.String()
try:
yield sys.stdout, sys.stderr
finally:
sys.stdout = save_stdout
sys.stderr = save_stderr
您将其用作
with out_redirected() as out, err:
runner.push(code)
out.seek(0)
print out.read()