在Python中显示exec的当前输出

时间:2013-02-05 13:03:10

标签: python exec

我运行的代码如下(从其他主题复制并添加了sleep):

import sys
import StringIO
import contextlib

@contextlib.contextmanager
def stdoutIO(stdout=None):
    old = sys.stdout
    if stdout is None:
        stdout = StringIO.StringIO()
    sys.stdout = stdout
    yield stdout
    sys.stdout = old

code = """
import time
i = [0,1,2]
for j in i :
    print j
    time.sleep(5)
"""
with stdoutIO() as s:
    exec code

print "out:", s.getvalue()

当我运行此代码时,我必须等待15秒,直到程序结束才能看到输出。 但是,我应该怎么做才能每隔5秒在print循环的每次迭代中看到for语句的输出?不要等待15秒才能看到整个输出。

这有可能吗? 是否可以看到exec的当前输出?

2 个答案:

答案 0 :(得分:1)

这个问题与exec无关。问题与您将stdout重定向到StringIO有关。所有打印语句都将内容添加到StringIO,而不是打印到屏幕。因此,您没有看到任何输出。唯一在屏幕上打印内容的行是

print "out:", s.getvalue()

在15秒睡眠后发生。


with stdoutIO() as s:
    ...

stdout重定向到StringIO.StringIO。只有在with上下文完成后,stdout才会重定向到原始sys.stdout,并打印到终端。


因此,要在执行print语句时从exec获取输出,只需删除stdeoutIO上下文管理器:

import sys

code = """
import time
i = [0,1,2]
for j in i :
    print j
    time.sleep(5)
"""

exec code

答案 1 :(得分:1)

在您发布的代码中,上下文管理器仅在执行with时产生一次。因此代码必须首先执行(所有15秒),所有代码输出都存储在StringIO对象中。因此,使用这样的代码,无法在写入时获得输出。

如果您想动态输出,则需要提供自己的file - 类,而不是StringIO,并覆盖write方法。例如(仅限示例,非常快速和脏代码):

import sys
import StringIO
import contextlib

class Proxy(object):
    def __init__(self,stdout,stringio):
        self._stdout = stdout
        self._stringio = stringio
    def __getattr__(self,name):
        if name in ('_stdout','_stringio','write'):
            object.__getattribute__(self,name)
        else:
            return getattr(self._stringio,name)
    def write(self,data):
         self._stdout.write(data)
         self._stringio.write(data)

@contextlib.contextmanager
def stdoutIO(stdout=None):
    old = sys.stdout
    if stdout is None:
        stdout = StringIO.StringIO()
    sys.stdout = Proxy(sys.stdout,stdout)
    yield sys.stdout
    sys.stdout = old

code = """
import time
i = [0,1,2]
for j in i :
    print j
    time.sleep(5)
"""

with stdoutIO() as s:
    exec code

print "out:", s.getvalue()

输出:

0
1
2
out: 0
1
2

前三行以5秒的间隔打印。最后三个一个在最后。