【问题标题】:How to check for EOF in Python?如何在 Python 中检查 EOF?
【发布时间】:2010-01-03 03:43:13
【问题描述】:

如何在 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 =(

标签: python eof


【解决方案1】:

您可能会发现使用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]

另一种选择是使用regular expression 来匹配分隔符:

def get_text_blocks(filename):
    import re
    seperator = re.compile('^-- -.*', re.M)
    with open(filename,'r') as f:
        return re.split(seperator, f.read())

【讨论】:

  • 有趣的答案马克。我不知道 itertools,谢谢。
  • +1 对于 RegEx 版本,itertools 版本略显神秘。
  • 我在 ineractive 解释器上尝试了 itertools 版本,它返回一个空字符串。行似乎是一个 itertools._grouper 对象
  • 不太可能返回空字符串。它总是返回一个列表。您一定有一个复制/粘贴错误。
  • 对不起,我的意思是一个空列表。
【解决方案2】:

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

【讨论】:

  • 谢谢亚历克斯!我的肮脏解决方案是在 for 块下方添加 text_blocks.append(text_block.getvalue()) 和 text_block.close() 。它有效,但它不干燥:/
【解决方案3】:

这是发射缓冲区的标准问题。

您没有检测到 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

【讨论】:

    【解决方案4】:

    这里为什么需要 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
    

    但是两个版本对我来说都有些难看,reg-ex 版本更干净。

    【讨论】:

    • 那仍然错过了最后一个区块。
    • 能否提供测试输入数据?
    • @maiku 测试输入数据是 phpMyAdmin 的 SQL 转储。我需要用以 -- -... 开头的行分隔块中的文本
    • 是的,我现在明白了,误解了任务。
    • 现在我得到 'IndexError: list index out of range'
    【解决方案5】:

    这是查看是否有空文件的快速方法:

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

    【讨论】:

    • 不,因为''之间没有空格。我在一个只有空格的文件上测试了这个,它没有检测到文件是空的。
    • 如果文件包含空格,则它不为空。
    • AndroidDebaser:这是一个不完整的答案。 f.read(1) 将消耗 1 个字符(您的单个空格),因此它需要处于循环中,像 while f.read(1) != '': 这样的东西会迭代,直到没有任何东西可以迭代。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-04-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-18
    • 2019-04-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多