定义 xrange 后的 StopIteration
StopIteration after defining xrange
我编写了以下代码来在文本文件中定义 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
如果您的文件中的行数不能除以 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
因为您只在一处而不是两处推进迭代器。
您的示例输入已经显示了问题:那里有 10 行,不能被 4 整除。所以当您阅读最后一个块时,您会得到 line1
和 line2
但是对于next()
调用 line3
,输入已用完,您什么也得不到。
您的完整输入文件中可能也有同样的问题:行数根本不能被 4 整除。
有几种方法可以克服这个问题。最好的办法可能是修复你的输入,因为你似乎一直期待四行,如果这不是输入文件给出的内容,那么似乎存在内容问题。
另一个非常简单的修复方法是使用 next()
:
指定默认值
line2, line3, line4 = [next(input_file, '') for line in xrange(3)]
现在,当 next()
失败时,将返回默认值 ''
。因此,即使文件已用完,您仍然可以获得一些内容。
然而,一个可能更好的解决方案是修复您迭代文件的方式。您有两个位置可以访问同一个文件迭代器,一次在外部 for 循环中,三次在列表理解中。它可能看起来很简单,所以你不会 运行 陷入其他问题,但你真的应该尝试改变它,这样你只有一个位置可以遍历迭代器;或者只使用 next()
调用,但将它与 for 循环混合似乎是个坏主意。
例如,您可以使用 grouper
itertools
recipe 以四个一组的方式干净地迭代文件:
with open(filename1, 'r') as input_file:
for line1, line2, line3, line4 in grouper(input_file, 4, fillvalue=''):
# do things with the lines
您有 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"
我编写了以下代码来在文本文件中定义 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
如果您的文件中的行数不能除以 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
因为您只在一处而不是两处推进迭代器。
您的示例输入已经显示了问题:那里有 10 行,不能被 4 整除。所以当您阅读最后一个块时,您会得到 line1
和 line2
但是对于next()
调用 line3
,输入已用完,您什么也得不到。
您的完整输入文件中可能也有同样的问题:行数根本不能被 4 整除。
有几种方法可以克服这个问题。最好的办法可能是修复你的输入,因为你似乎一直期待四行,如果这不是输入文件给出的内容,那么似乎存在内容问题。
另一个非常简单的修复方法是使用 next()
:
line2, line3, line4 = [next(input_file, '') for line in xrange(3)]
现在,当 next()
失败时,将返回默认值 ''
。因此,即使文件已用完,您仍然可以获得一些内容。
然而,一个可能更好的解决方案是修复您迭代文件的方式。您有两个位置可以访问同一个文件迭代器,一次在外部 for 循环中,三次在列表理解中。它可能看起来很简单,所以你不会 运行 陷入其他问题,但你真的应该尝试改变它,这样你只有一个位置可以遍历迭代器;或者只使用 next()
调用,但将它与 for 循环混合似乎是个坏主意。
例如,您可以使用 grouper
itertools
recipe 以四个一组的方式干净地迭代文件:
with open(filename1, 'r') as input_file:
for line1, line2, line3, line4 in grouper(input_file, 4, fillvalue=''):
# do things with the lines
您有 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"