我运行的代码如下(从其他主题复制并添加了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的当前输出?
答案 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秒的间隔打印。最后三个一个在最后。