如何在Python中检查文件结尾(EOF)?

9

如何在Python中检查EOF?我发现我的代码有一个错误,分隔符后的最后一个文本块没有添加到返回列表中。或者也许有更好的方式来表达这个函数?

这是我的代码:

def get_text_blocks(filename):
    text_blocks = []
    text_block = StringIO.StringIO()
    with open(filename, 'r') as f:
        for line in f:
            text_block.write(line)
            print line
            if line.startswith('-- -'):
                text_blocks.append(text_block.getvalue())
                text_block.close()
                text_block = StringIO.StringIO()
    return text_blocks

现在试试,我修复了我的函数x2 =( - Maiku Mori
5个回答

2
你可能会发现使用itertools.groupby更容易解决这个问题。
def get_text_blocks(filename):
    import itertools
    with open(filename,'r') as f:
        groups = itertools.groupby(f, lambda line:line.startswith('-- -'))
        return [''.join(lines) for is_separator, lines in groups if not is_separator]

另一种选择是使用正则表达式来匹配分隔符:
def get_text_blocks(filename):
    import re
    seperator = re.compile('^-- -.*', re.M)
    with open(filename,'r') as f:
        return re.split(seperator, f.read())

很有趣的回答,Mark。我不知道itertools,谢谢。 - ajushi
+1 对于正则表达式版本,itertools 版本有点晦涩。 - Maiku Mori
我在交互式解释器上尝试了itertools版本,它返回一个空字符串。lines似乎是一个itertools._grouper对象。 - ajushi
不太可能返回空字符串。它总是返回一个列表。你一定有复制/粘贴错误。 - Mark Byers
抱歉,我的错误。我是指一个空列表。 - ajushi
显示剩余2条评论

1

这是生成缓冲区的标准问题。

您不必检测EOF。您只需写入最后一个缓冲区即可。

def get_text_blocks(filename):
    text_blocks = []
    text_block = StringIO.StringIO()
    with open(filename, 'r') as f:
        for line in f:
            text_block.write(line)
            print line
            if line.startswith('-- -'):
                text_blocks.append(text_block.getvalue())
                text_block.close()
                text_block = StringIO.StringIO()
         ### At this moment, you are at EOF
         if len(text_block) > 0:
             text_blocks.append( text_block.getvalue() )
         ### Now your final block (if any) is appended.
    return text_blocks

1

for语句终止时,文件末尾条件成立--这似乎是最简单的方法来轻微修复此代码(如果您想在附加之前检查它是否为空,可以在结尾处提取text_block.getvalue())。


谢谢Alex!我的临时解决方案是在for循环块下面添加text_blocks.append(text_block.getvalue())和text_block.close()。它能够工作,但不够DRY :/ - ajushi

-1

为什么在这里需要StringIO?

def get_text_blocks(filename):
    text_blocks = [""]
    with open(filename, 'r') as f:
        for line in f:
            if line.startswith('-- -'):
                text_blocks.append(line)
            else: text_blocks[-1] += line          
    return text_blocks

编辑:修复了函数,其他建议可能更好,只是想编写一个类似于原始函数的函数。

编辑:假设文件以“-- -”开头,通过向列表添加空字符串,您可以“修复”IndexError,或者您可以使用此方法:

def get_text_blocks(filename):
    text_blocks = []
    with open(filename, 'r') as f:
        for line in f:
            if line.startswith('-- -'):
                text_blocks.append(line)
            else:
                if len(text_blocks) != 0:
                    text_blocks[-1] += line          
    return text_blocks

但是两个版本对我来说都有点丑,正则表达式版本更加干净。


那仍然错过了最后一个块。 - Mark Byers
请提供测试输入数据。 - Maiku Mori
@maiku 测试输入数据是由phpMyAdmin生成的SQL转储。我需要将文本分成以-- -开头的行分隔的块。 - ajushi
是的,我现在明白了,误解了任务。 - Maiku Mori
现在我收到了“IndexError: list index out of range”的错误。 - Mark Byers
显示剩余2条评论

-2

这是一种快速检查文件是否为空的方法:

if f.read(1) == '': 
 print "EOF"
 f.close()

不行,因为''之间没有空格。我在一个只有一个空格的文件上进行了测试,它没有检测到该文件为空。 - AndroidDebaser
2
如果一个文件名包含空格,那么它并不是空的。 - Dave
AndroidDebaser:这是一个不完整的答案。f.read(1)将消耗1个字符(您的单个空格),因此它需要在循环中,类似于while f.read(1) != '':会迭代直到没有可迭代的内容。 - Gary Howe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接