我编写了以下代码来定义文本文件中的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
答案 0 :(得分:2)
您的示例输入已经显示了问题:您有10行,不能被4分割。因此当您阅读最后一个块时,您会获得line1
和line2
但{ {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"