СтопИтерация показывает случайным образом при запуске кода

1

Я очень новичок в Python, и я пытаюсь собрать небольшую программу, которая, похоже, работает, однако я часто получаю ошибку ниже при запуске кода.

Конечная цель немного сложнее, чем текущий код, однако идея состоит в том, что программа считывает из двух отдельных файлов CSV, выбирает случайную строку из каждого, затем объединяет определенные значения из этих строк и печатает результат.

Ошибка:

    Traceback (most recent call last):
  File ".\SimulationScript.py", line 57, in <module>
    counter(10)
  File ".\SimulationScript.py", line 45, in counter
    indicatorDefinition(indicator_file)
  File ".\SimulationScript.py", line 17, in indicatorDefinition
    chosen_row = next(row for row_number, row in enumerate(reader)
StopIteration

Код:

from sys import argv
import random
import csv

script, file1, file2 = argv
f1 = ''
f2 = ''

def iDefinition(i):
    with open(i) as file:
        lines = sum(1 for line in file)
        line_number = random.randrange(lines)

    with open(i) as file:
        reader = csv.DictReader(file)
        chosen_row = next(row for row_number, row in enumerate(reader)
            if row_number == line_number)

        global f1
        f1 = chosen_row['field_1']+'":"'+chosen_row['value_1']+'"'

def nDefinition(n):
    with open(n) as file:
        lines = sum(1 for line in file)
        line_number = random.randrange(lines)

    with open(n) as file:
        reader = csv.DictReader(file)
        chosen_row = next(row for row_number, row in enumerate(reader)
            if row_number == line_number)

        global f2
        f2 = '"code":"'+chosen_row['Node code']+'","'



def counter():
    count = 0

    while count < 6:
        nDefinition(file2)
        iDefinition(file1)
        print(f2+f1)

        count += 1

counter()
  • 0
    Когда вы выбрали случайный номер строки, возможно, он получил последнюю строку. а затем selected_row = next (), следующего нет.
  • 0
    Насколько велики эти файлы и как часто вы хотите взять одну строку у них?
Теги:
python-3.x

3 ответа

0
Лучший ответ

Как уже упоминалось, StopIteration возникает при попытке уничтожить элемент из исчерпанного итерабельного.

it = iter([1, 2])
next(it)
# 1
next(it)
# 2
next(it)
# raises StopIteration as nothing to return
# however you can use the default argument to return a default value when exhausted
# next(it, 'cabbage!')
# cabbage!

Однако, поскольку вы хотите только брать произвольную строку из файла, вместо того, чтобы подсчитывать строки и выбирать номер строки, затем сканировать файл и извлекать эту строку, вы можете использовать min со случайным ключом и делать это в одном проход, например:

import heapq, random

with open('your_file') as fin:
    random_line = min(fin, key=lambda L: random.random())

Если вы хотите принять более 1, вы можете использовать heapq как таковой:

with open('your_file') as fin:
    random_50 = heapq.nlargest(50, fin, key=lambda L: random.random())

Если файлы не собираются взорвать системную память, и вы захотите взять случайную строку, вы можете загрузить их в list а затем использовать random.choice, например:

with open('your_file') as fin:
    data = list(fin)

r1 = random.choice(data)
r2 = random.choice(data)
# ...
  • 1
    Я изменил свой код для использования метода heapq :) Мне нужно изучить этот метод, чтобы понять его полностью, не совсем уверенный, с чем связаны все аргументы.
  • 0
    @RTSecurity heapq документации объясняет это довольно хорошо ... Я склонен думать об этом как список фиксированного размера , где , как только это полная, если элемент будет добавлен имеет больший ключ , чем любой из существующих элементов, самый низкий шпонкой элемент получает переехал, и новый элемент переехал ...
Показать ещё 3 комментария
0

Как взято из https://docs.python.org/3/glossary.html#term-iterator:

Когда больше нет данных, вместо этого возникает исключение StopIteration. На этом этапе объект итератора исчерпан, и любые дальнейшие вызовы его __next__() снова вызывают StopIteration.

enumerate() возвращает объект Iterator, поэтому вышеупомянутый случай. Предположительно, ваш скрипт достиг последней строки в CSV, и ваш вызов next() требует, чтобы Iterator возвратил другой (что, конечно, невозможно).

Поскольку ожидается это исключение, вы можете захотеть окружить выражение в блоке try-except, уловить исключение StopIteration, а затем продолжить выполнение вашего метода.

Другой вариант - использовать for-loop, который просто останавливается после повторного итерации последнего элемента. next() обычно используются только тогда, когда вам нужно контролировать, когда будет выбран следующий элемент, но нет, если вы хотите перебрать все за один раз.

0

StopIterationError получает следующее, когда итерируемый объект полностью переименован. Это не должно происходить случайно, но каждый раз, когда вы запускаете код после того, как итерация прошла через весь итерируемый объект.

Либо вы создаете блок try/except, либо используете цикл for вместо следующего. (Цикл for в python автоматически улавливает и "игнорирует" ошибку остановки после завершения цикла).

    row for row_number, row in enumerate(reader):
        if row_number == line_number:
            chosen_row = row

Ещё вопросы

Сообщество Overcoder
Наверх
Меню