Лучший способ хранить и использовать большой текстовый файл в Python - PullRequest
4 голосов
/ 01 октября 2008

Я создаю сетевой сервер для ошеломляющего клона, который я написал на python, который принимает пользователей, решает доски и оценивает входные данные игрока. Файл словаря, который я использую, имеет размер 1,8 МБ (словарь ENABLE2K), и мне нужно, чтобы он был доступен для нескольких классов решателей игр. Прямо сейчас у меня это так, что каждый класс перебирает файл построчно и генерирует хеш-таблицу (ассоциативный массив), но чем больше решающих классов я создаю, тем больше памяти занимает.

Что я хотел бы сделать, так это импортировать файл словаря один раз и передавать его каждому экземпляру решателя по мере необходимости. Но каков наилучший способ сделать это? Должен ли я импортировать словарь в глобальном пространстве, а затем обращаться к нему в классе решателя как globals () ['dictionary']? Или я должен импортировать словарь, а затем передать его в качестве аргумента в конструктор класса? Один из них лучше другого? Есть ли третий вариант?

Ответы [ 4 ]

10 голосов
/ 01 октября 2008

Если вы создаете модуль dictionary.py, содержащий код, который читает файл и создает словарь, этот код будет выполняться только при первом его импорте. Дальнейший импорт вернет ссылку на существующий экземпляр модуля. Таким образом, ваши классы могут:

import dictionary

dictionary.words[whatever]

где dictionary.py имеет:

words = {}

# read file and add to 'words'
1 голос
/ 02 октября 2008

Адам, помни это в Python, когда говоришь:

a = read_dict_from_file()
b = a

... вы на самом деле не копируете a, и, таким образом, используя больше памяти, вы просто делаете b другую ссылку на тот же объект.

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

Какой из них наиболее питоновский? Это целая «банка червей», но вот что я бы сделал лично:

def main(args):
  run_initialization_stuff()
  dictionary = read_dictionary_from_file()
  solvers = [ Solver(class=x, dictionary=dictionary) for x in len(number_of_solvers) ]

НТН.

1 голос
/ 01 октября 2008

Несмотря на то, что на данном этапе это, по сути, одиночка, применяются обычные аргументы против глобалов. Чтобы найти питон-синглтон-заменитель, найдите объект "borg".

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

0 голосов
/ 01 октября 2008

В зависимости от того, что содержит ваш диктант, вас могут заинтересовать модули shelve или anydbm. Они дают вам подобные интерфейсы (просто строки как ключи и элементы для anydbm, строки как ключи и любые объекты python как элементы для shelve), но данные на самом деле находятся в файле DBM (gdbm, ndbm, dbhash, bsddb, в зависимости от того, что доступно на платформе.) Вы, вероятно, все еще хотите разделить фактическую базу данных между классами, как вы просите, но это позволит избежать шага синтаксического анализа текстового файла, а также сохранения его всего в Бит памяти.

...