将打印重定向到字符串列表?

时间:2014-01-24 19:40:18

标签: python

我知道如何将打印重定向到文件。

import sys

orig_stdout = sys.stdout
f = file('out.txt', 'w')
sys.stdout = f

for i in range(2):
    print ('i = ', i)

sys.stdout = orig_stdout
f.close()

我需要做同样的事情但是没有文件:将打印输出保留在字符串列表中。如何在Py3k中完成?

编辑:我可以在中间部分进行第三方打印,而不是我自己的打印,因此代码必须是通用的“print()”通用。

4 个答案:

答案 0 :(得分:14)

import sys
class ListStream:
    def __init__(self):
        self.data = []
    def write(self, s):
        self.data.append(s)

sys.stdout = x = ListStream()

for i in range(2):
    print ('i = ', i)

sys.stdout = sys.__stdout__
print(x.data)

产量

['i = ', ' ', '0', '\n', 'i = ', ' ', '1', '\n']

提示:您无需保存原始sys.stdout

orig_stdout = sys.stdout

因为sys.stdout可以通过

重置
sys.stdout = sys.__stdout__

您还可以通过将ListStream设置为上下文管理器来添加一些语法糖:

import sys
class ListStream:
    def __init__(self):
        self.data = []
    def write(self, s):
        self.data.append(s)
    def __enter__(self):
        sys.stdout = self
        return self
    def __exit__(self, ext_type, exc_value, traceback):
        sys.stdout = sys.__stdout__  

通过添加__enter____exit__方法,您现在可以在ListStream中使用with-statement会自动重置sys.stdout当Python退出with-suite

时为你服务
with ListStream() as x:
    for i in range(2):
        print ('i = ', i)

print(x.data)

答案 1 :(得分:5)

我认为最简单的方法是使用sys.stdout实例替换TextIOWrapper(只是StringIO),而不是滚动自己的类,而是保留对它的引用:

import sys
from io import StringIO

s = StringIO()

sys.stdout = s

print('yo')

print('this is stuff')

print('hi')

s.getvalue()
Out[38]: 'yo\nthis is stuff\nhi\n'

s.getvalue().splitlines()
Out[39]: ['yo', 'this is stuff', 'hi']

正如@unutbu所说,您可以使用sys.stdout = sys.__stdout__恢复原始标准输出;我特别喜欢使用上下文管理器暂时将stdout重定向到你想要的位置。

答案 2 :(得分:1)

当我需要构建ncurses应用程序时,我经常这样做:

import sys

# in this wrapper class you can use a string list instead of a full string like I'm doing
class StdOutWrapper:
    lines = []
    def write(self,txt):
        self.lines.append(txt)

    # here is a method so you can get stuff out of your wrapper class
    # I am rebuilding the text, but you can do whatever you want!
    def get_text(self,beg,end):
        return '\n'.join(self.lines)

mystdout = StdOutWrapper()
sys.stdout = mystdout
sys.stderr = mystdout

# do your stuff here that needs to be printed out in a string list
for i in range(2):
    print ('i = ', i)

# you don't need to make your variable to cache the `stdout`/`stderr` as they still exist
sys.stdout = sys.__stdout__
sys.stderr = sys.__stderr__

它与python 3和python 2一起工作正常。

答案 3 :(得分:0)

我会编写一个函数来为你完成,而不是试图将stdout重定向到一个列表(我认为它无论如何都不会起作用,但不要引用我的话)。< / p>

def lprint(text):
    global string_list
    try: string_list.append(text)
    except NameError as e:
        string_list = [text]

for i in range(2):
    lprint ("i = {}".format(i))

print(string_list)
[OUT]: ["i = 0","i = 1"]