Альтернативы хранению больших списков в памяти (Python)

Если у меня есть список (или массив, словарь....) в Python, который мог бы превысить доступное пространство адреса памяти, (Python на 32 бита), каковы опции и там относительные скорости? (кроме не вхождения в список, настолько большой), список мог превысить память, но у меня нет способа знать перед рукой. После того как это запускает чрезмерные 75%, которые я хотел бы больше не сохранить списком в памяти (или новые объекты так или иначе), есть ли способ преобразовать в основанную на файле середину реки подхода?

Что является лучшим (скорость в и) опции хранилища файлов?

Просто должен сохранить простой список чисел. никакая потребность к случайному Энному доступу элемента, просто добавьте/вытолкайте операции типа.

12
задан Zahra 9 June 2017 в 14:46
поделиться

8 ответов

Если ваши "числа" достаточно просты (подписанные или неподписанные целые числа до 4 байт каждое, или с плавающей точкой по 4 или 8 байт каждое), я рекомендую стандартную библиотеку array module как лучший способ сохранить несколько миллионов из них в памяти ("tip" вашего "виртуального массива") с бинарным файлом (открытым для бинарного R/W), поддерживающим остальную часть структуры на диске. array.array имеет очень быстрые методы из файла и tofile для облегчения перемещения данных туда и обратно.

т.е, в основном, предполагая, например, беззнаковые длинные числа, что-то вроде:

import os

# no more than 100 million items in memory at a time
MAXINMEM = int(1e8)

class bigarray(object):
  def __init__(self):
    self.f = open('afile.dat', 'w+')
    self.a = array.array('L')
  def append(self, n):
    self.a.append(n)
    if len(self.a) > MAXINMEM:
      self.a.tofile(self.f)
      del self.a[:]
  def pop(self):
    if not len(self.a):
      try: self.f.seek(-self.a.itemsize * MAXINMEM, os.SEEK_END)
      except IOError: return self.a.pop()  # ensure normal IndexError &c
      try: self.a.fromfile(self.f, MAXINMEM)
      except EOFError: pass
      self.f.seek(-self.a.itemsize * MAXINMEM, os.SEEK_END)
      self.f.truncate()
    return self.a.pop()

Конечно, вы можете добавлять другие методы по мере необходимости (например, отслеживать общую длину, добавлять extension, что угодно), но если pop и append действительно все, что вам нужно, это должно служить.

.
14
ответ дан 2 December 2019 в 04:17
поделиться

Вероятно, существуют десятки способов хранения данных вашего списка в файле, а не в памяти. То, как вы решите это сделать, будет полностью зависеть от того, какие операции нужно выполнить с данными. Вам нужен случайный доступ к N-му элементу? Вам нужно выполнить итерацию по всем элементам? Будете ли вы искать элементы, которые соответствуют определенным критериям? Какую форму принимают элементы списка? Вы будете вставлять только в конце списка, или также в середине? Есть ли метаданные, которые вы можете хранить в памяти с большей частью элементов на диске? И так далее и так далее

Одна из возможностей - это структурировать ваши данные относительно друг друга и хранить их в базе данных SQLite

.
8
ответ дан 2 December 2019 в 04:17
поделиться

Ну, если вы ищете скорость и ваши данные числовые по своей природе, то вы можете рассмотреть возможность использования numpy и PyTables или h5py. Насколько я помню, интерфейс не так хорош, как простые списки, но масштабируемость просто фантастическая!

.
4
ответ дан 2 December 2019 в 04:17
поделиться

Проверили ли вы полочный питоновый модуль, основанный на огурце?

http://docs.python.org/library/shelve.html

2
ответ дан 2 December 2019 в 04:17
поделиться

Возможно, вы захотите рассмотреть другой вид структуры: не список, а придумывание, как сделать (свою задачу) с генератором или пользовательским итератором

.
1
ответ дан 2 December 2019 в 04:17
поделиться

А как насчет базы данных, ориентированной на документы?
Есть несколько альтернатив; я думаю, что самая известная на данный момент - это CouchDB, но вы также можете выбрать Tokyo Cabinet, или MongoDB. Последний имеет преимущество переплетения питона непосредственно из основного проекта, не требуя дополнительного модуля.

.
0
ответ дан 2 December 2019 в 04:17
поделиться

Современные операционные системы справятся с этим за вас, не беспокоясь об этом. Это называется виртуальной памятью .

0
ответ дан 2 December 2019 в 04:17
поделиться

Ответ очень "зависит от обстоятельств".

Что вы храните в списках? Струны? целые числа? Объекты?

Как часто список записывается по сравнению с тем, как его читают? Добавляются ли элементы только в конец, или записи могут быть изменены или вставлены в середину?

Если вы добавляете только в конец, запись в плоский файл может быть самой простой вещью, которая могла бы сработать.

Если вы храните объекты переменного размера, такие как строки, то, возможно, сохраните в памяти индекс начала каждой строки, чтобы вы могли быстро ее прочитать.

Если вам нужно поведение словаря, посмотрите на модули db - dbm, gdbm, bsddb и т. Д.

Если вам нужна запись с произвольным доступом, тогда, возможно, база данных SQL может быть лучше.

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

редактировать: Исходя из ваших обновленных требований, я бы выбрал плоский файл и сохранил буфер в памяти из последних N элементов.

6
ответ дан 2 December 2019 в 04:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: