2016-09-13 2 views
3

У меня проблема с большим итератором для цикла в коде ниже. Он генерирует float, читая список строк, содержащий числа.Ошибка переполнения Python: слишком большой индекс iter

def float_generator(tekstowe): 
     x = '' 
     for c in tekstowe: 
      if c != ' ': 
       x += c 
      else: 
       out = float(x) 
       x = '' 
       yield(out) 

Я получаю "OverflowError: ИТЭР индекс слишком велик". Я пытаюсь использовать действительно большие итерационные числа (например, миллиарды значений в искомом файле). Является ли его диапазон как-то ограниченным для циклов?

Использование Python 2.7 64 бит. Благодарю.

+0

Насколько велика 'float (x)' get? –

+0

Они оценены в 0-255 и выглядят немного случайными: 25.75000000 0.340 22.33333397 0.667. Я имею в виду, что это 4 примера float. –

+0

Ответ здесь: https://github.com/python/cpython/blob/efac0438f42e03f0ece269ac8f1616bc6dc2d8bd/Objects/iterobject.c#L57 и здесь https://docs.python.org/2/c-api/long.html# c.PyLong_AsSsize_t –

ответ

4

Похож tekstowe тип последовательности, которая реализует только __getitem__, не __iter__, поэтому он использует итератор оболочку Python, который вызывает __getitem__ с 0, то 1, 2, 3 и т.д., пока __getitem__ не поднимает IndexError.

В качестве детали реализации, Python 2.7.11 and higher limits the value of the index passed by the iterator wrapper to LONG_MAX (до 2.7.11 он не был проверен, но он все еще использовал long для хранения индекса, поэтому он будет обертывать и начинать индексирование с отрицательными значениями). Это не имеет значения для большинства не-Windows 64-разрядных построений, где LONG_MAX - 2**63 - 1 (больше, чем вы, вероятно, столкнулись), но в Windows C long s остается 32-битным количеством даже на 64-битных строках, поэтому LONG_MAX остается 2**31 - 1, которая достаточно низка для достижения человеческих времен.

варианта:

  1. Изменить реализацию любого класса tekstowe, чтобы дать ему истинный __iter__ метода, поэтому он не получает обернут последовательность итератора обертки, когда вы используете его
  2. Upgrade к Python 3.4+, в идеале 3.5 (2.7.10/3.4.3 и ниже lacks the check for overflow entirely), но это может означать, что wraparound вызывает бесконечный цикл: 3.4.4/3.5.0 added the check, and they use a signed size_t, testing against PY_SSIZE_T_MAX, что означает, что он не будет ошибкой, пока индекс не достигнет 2**63 - 1 на любой 64-битной сборке, Windows или иначе)

Изменения для добавления проверок переполнения были сделаны для разрешения Python bug #22939; изменение типа (от long до Py_ssize_t) для хранения индексатора итератора последовательности произошло в версии 3.4.0, разрешив Python bug #17932.

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