2015-12-23 2 views
1

Я написал следующий код для определения блоков из 4 строк в текстовом файле и вывода блока, если вторая строка блока состоит только из одного типа символов. Предполагается (и ранее подтверждено), что вторая строка всегда состоит из строки из 36 символов.StopIteration после определения xrange

# 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>[email protected] 
@1:1:1679:1032:Y 
CGGTGGATCACTCGGCTCGTGCGTCGATGAAGAACG 
+1

И 'for' петли и список понимания является перебором над файлом, возможно, вам следует рационализировать, что вплоть до одного цикла? – jonrsharpe

+0

У вас уже есть неявный 'next (input_file)' в вашем цикле for; вы считаете, что вы за один? –

+2

Число строк в вашем файле делится на '4'? –

ответ

2

Ваш пример ввода уже показывает проблему: У вас есть 10 строк там, что не divisble на 4. Так как вы читаете самый последний блок, вы получите line1 и line2 но для next() вызова для line3, вход истощены, и вы ничего не получаете.

Вполне вероятно, что у вас есть один и тот же вопрос в вашем полном входном файле, а также: Число строк просто не делится на 4.

Есть несколько способов, чтобы преодолеть это. Лучше всего, наверное, исправить ваш вход, так как вы, кажется, ожидаете четырех строк на всем пути, похоже, проблема с содержимым, если это не то, что дает входной файл.

Другой очень простое решение проблемы было бы указать значение по умолчанию с next():

line2, line3, line4 = [next(input_file, '') for line in xrange(3)] 

Теперь, когда next() потерпит неудачу, то значение по умолчанию '' вместо этого вернулся. Поэтому, даже если файл исчерпан, вы все равно получаете некоторый контент.

Возможно, лучшим решением было бы исправить то, как вы перебираете файл. У вас есть два места, где вы получаете доступ к одному и тому же файловому итератору, один раз во внешнем цикле и три раза в понимании списка. Это может показаться достаточно простым, чтобы вы не столкнулись с другими проблемами, но вы действительно должны попытаться изменить это, чтобы у вас было только одно место, где вы проходите через итератор; или только когда-либо используют вызовы next(), но смешивание их с циклом for кажется плохой идеей.

Вы могли бы, например, использовать grouperitertools recipe для чисто итерации файла в группах по четырем:

with open(filename1, 'r') as input_file: 
    for line1, line2, line3, line4 in grouper(input_file, 4, fillvalue=''): 
     # do things with the lines 
+0

"или использовать только следующие() вызовы" <- Извините, что вы подразумеваете под этим? В настоящее время я пытаюсь решить ваше решение, но я думаю, что мне нужно сначала проверить «itertools». – biohazard

+1

С этим я имею в виду то, что показал Майк Мюллер во втором примере; я хочу сказать, что вы не должны иметь как цикл for, так и индивидуальный 'next()' вызывает итерацию файла. Вместо этого у вас должен быть только один способ итерации файла, например. либо с помощью цикла for, либо с помощью 'next()' вызовов. Таким образом, вы всегда точно знаете, когда и почему файл повторяется. – poke

+0

Я действительно пробовал, но я не смог использовать функцию 'grouper()' даже после проверки ссылки, которую вы предоставили. Возможно, я слишком много новичок, но решение Майка Мюллера было самым простым и легким для меня, поэтому, после тщательного рассмотрения, я выберу его (один из них был похож, но нет необходимости печатать сообщения об ошибках для вывода). В очередной раз благодарим за помощь! – biohazard

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 

потому, что вы продвигаетесь только итератор в одном месте не в два.

1

Вы 10 линии, поэтому он может перебирать 2 раз, а затем есть нехватка 2 линии. Здесь Python не может читать достаточно строк и выбрасывает StopIteration.

Checkout этого код, я немного обновил его:

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" 
+0

Это приятное улучшение, спасибо большое! – biohazard

+0

@poke Причина, по которой мне понравился этот ответ, потому что он научил меня чему-то о том, как использовать исключения. @Abu Ашраф Маснун не должен быть 'xrange (3)'? – biohazard

+0

Я предлагаю вам отметить ответ @ poke, так как он детализировал его больше, чем я. Я в порядке, не получив ответа. – masnun

Смежные вопросы