定义xrange后的StopIteration

时间:2015-12-23 10:57:58

标签: python python-2.x stopiteration

我编写了以下代码来定义文本文件中的4行块,如果块的第2行只由一种类型的字符组成,则输出该块。假设(并且先前已验证)第二行总是由36个字符的字符串组成。

# filter out homogeneous reads

import sys
import collections
from collections import Counter

filename1 = sys.argv[1] # file to process

with open(filename1,'r') as input_file:
    for line1 in input_file:
        line2, line3, line4 = [next(input_file) for line in xrange(3)]
        c = Counter(line2).values() # count characters in line2
        c.sort(reverse=True) # sort values in descending order
        if c[0] < 36:
            print line1 + line2 + line3 + line4.rstrip()

但是,我收到如下StopIteration错误。如果有人能告诉我原因,我将不胜感激。

$ python code.py test.file > testout.file
Traceback (most recent call last):
  File "code.py", line 11, in <module>
    line2, line3, line4 = [next(input_file) for line in xrange(3)]
StopIteration

任何帮助都将受到赞赏,特别是那种解释我的特定代码有什么问题以及如何解决它的方法。以下是输入示例:

@1:1:1323:1032:Y
AGCAGCATTGTACAGGGCTATCATGGAATTCTCGGG
+1:1:1323:1032:Y
HHHBHHBHBHGBGGGH8HHHGGGGFHBHHHHBHHHH
@1:1:1610:1033:Y
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+1:1:1610:1033:Y
HHEHHHHHHHHHHHBGGD>GGD@G8GGGGDHBHH4C
@1:1:1679:1032:Y
CGGTGGATCACTCGGCTCGTGCGTCGATGAAGAACG

3 个答案:

答案 0 :(得分:2)

您的示例输入已经显示了问题:您有10行,不能被4分割。因此当您阅读最后一个块时,您会获得line1line2但{ {1}}要求next(),输入已用尽,您什么也得不到。

您的完整输入文件中可能存在相同的问题:行数不能被4整除。

有几种方法可以解决这个问题。最好的可能是修复你的输入,因为你似乎一直期待四行,如果这不是输入文件给出的话,似乎存在内容问题。

另一个非常简单的解决方法是使用line3指定默认值:

next()

现在,当line2, line3, line4 = [next(input_file, '') for line in xrange(3)] 失败时,会返回默认值next()。因此,即使文件已耗尽,您仍然可以获得一些内容。

然而,一个可能更好的解决方案是修复迭代文件的方式。您有两个位置可以访问同一个文件迭代器,一个位于外部for循环中,三个位于列表解析中。它可能看起来很简单,所以你不会遇到其他问题,但是你应该真的尝试改变它,这样你只有一个位置,你可以通过迭代器;或者只使用''次调用,但将它与for循环混合似乎是一个坏主意。

例如,您可以使用next() itertools recipe以四个为一组干净地迭代文件:

grouper

答案 1 :(得分:1)

如果文件中的行数除以4而没有余数,则会得到此值。然后你会尝试读一条不存在的行。你需要计算空行。

如果行数不足以进行处理,一种解决方案是停止处理文件:

try:
    line2, line3, line4 = [next(input_file) for line in xrange(3)]
except StopIteration:
    break

感觉有点清洁:

while True:
    try:
        line1, line2, line3, line4 = [next(input_file) for line in xrange(4)]
except StopIteration:
    break

因为你只在一个地方而不是两个地方进行迭代器。

答案 2 :(得分:1)

您有10行,因此可以迭代2次,然后2行短缺。这是Python无法读取足够的行并抛出StopIteration的地方。

查看此代码,我稍微更新了一下:

import sys
import collections
from collections import Counter

filename1 = sys.argv[1] # file to process

with open(filename1,'r') as input_file:
    while True:
        try:
            line1, line2, line3, line4 = [next(input_file) for line in xrange(4)]
        except StopIteration:
            print "Not enough lines to read!"
            break

        c = Counter(line2).values() # count characters in line2
        c.sort(reverse=True) # sort values in descending order
        if c[0] < 36:
            print line1 + line2 + line3 + line4.rstrip()
        else:
            print "Skipping 4 lines since less than 36 characters"