在python中读取捕获的标准输出中的行

在python中读取捕获的标准输出中的行,python,python-2.7,Python,Python 2.7,我试图捕获stdout,然后在调用函数后解析它。我是通过cStringIO.StringIO对象来实现的,但是readline调用不会产生任何结果。我创建了以下测试来向您展示发生了什么: import cStringIO, sys def readstream(s): c = s.getvalue() for i in c.split('\n'): yield i old_stdout = sys.stdout stream = cStringIO.Strin

我试图捕获stdout,然后在调用函数后解析它。我是通过cStringIO.StringIO对象来实现的,但是readline调用不会产生任何结果。我创建了以下测试来向您展示发生了什么:

import cStringIO, sys

def readstream(s):
    c = s.getvalue()
    for i in c.split('\n'):
        yield i

old_stdout = sys.stdout
stream = cStringIO.StringIO()
sys.stdout = stream

print ('testing this stuff')
print ('more testing of this')

sys.stdout = old_stdout

print 'getvalue:'
print stream.getvalue()

print 'readlines:'
for line in stream.readlines():
    print line

print 'readstream:'
for line in readstream(stream):
    print line
生成的输出为:

getvalue:
testing this stuff
more testing of this

readlines:
readstream:
testing this stuff
more testing of this
为什么stream.readlines()什么也不产生


谢谢

您刚刚完成对
流的写入
,因此它的文件指针位于文件的末尾

readlines
返回当前文件指针到文件末尾的所有行。由于从文件结尾到文件结尾没有行,因此它不会返回任何行

如果要将文件指针移回文件的开头,请使用以下方法:


一些旁注:

首先,尤其是在这种情况下。一个文件已经是该文件中行的一部分;没有理由仅仅为了迭代而创建相同行的列表。这将为您提供完全相同的结果:

stream.seek(0)
for line in stream:
    print line
…但更简单、更快且不浪费内存

其次,您的
readstream
函数比需要的复杂得多。通常情况下,生成值的生成器比列表更具优势。它们让调用者在每个值都可用时就开始处理这些值,而不是等到它们全部完成,它们不会浪费内存来创建一个列表,只是为了对其进行迭代等等。但在这种情况下,您已经在通过调用
split
,来创建列表了,因此,您不妨将其退回:

def readstream(s):
    c = s.getvalue()
    return c.split('\n')

这里并没有关于捕获的stdout的具体内容,它增加了许多读者可能不理解的额外复杂性。如果你只使用
stream.write
print>>stream
,你会遇到完全相同的问题,这将是一个更为普遍有用的问题。@abarnert你说得对,问题不是关于stdout的,但我写问题时并不知道它。我在以前的场合使用过readlines,它工作得很好,所以我认为这是stdout重定向特有的。因此,标题指的是标准输出。在检查您的答案之后,很明显,它与标准输出无关,而是与文件IO管理有关,但无论如何,这是像我这样的新手可能遇到的问题。在开始提问之前,我尝试通过再次关闭和打开流来做同样的事情。关闭很容易,但是打开方法在cStringIO中不可用。现在读你的答案似乎很简单。谢谢@维克多:好吧,对于一个真实的文件,你可以关闭它,然后用相同的路径名打开一个新文件。(当然,除非文件已被取消链接或替换!)使用StringIO,否则没有路径名;等效的方法是关闭它,并使用旧的
getvalue()
…创建一个新的StringIO,但这样做有点愚蠢。我现在已经从python的有用命令列表中删除了readlines。谢谢你提供这个有点离题的信息。
def readstream(s):
    c = s.getvalue()
    return c.split('\n')