0

I am running code as follows (copied from other topic and added 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()

When I run this code I have to wait 15 seconds until the program ends to see the output. But what should I do to see the output of the print statement in each iteration of the for loop every 5 seconds? Not to wait 15 seconds to see the whole output.

Is this possible at all? Is it possible to see the current output of exec?

4

2 回答 2

1

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

print "out:", s.getvalue()

这发生在 15 秒的睡眠后。


with stdoutIO() as s:
    ...

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


因此,要在打印语句发生时从 exec 获取输出,只需删除stdeoutIO上下文管理器:

import sys

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

exec code
于 2013-02-05T13:25:17.733 回答
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 秒的间隔打印。最后三人合而为一。

于 2013-02-05T13:27:45.513 回答