Лучший способ хранить и использовать большой текстовый файл в Python
Я создаю сетевой сервер для ошеломляющего клона, который я написал на python, который принимает пользователей, решает доски и оценивает входные данные игрока. Файл словаря, который я использую, имеет размер 1,8 МБ (словарь ENABLE2K), и мне нужно, чтобы он был доступен для нескольких классов решателей игр. Прямо сейчас у меня так, что каждый класс перебирает файл построчно и генерирует хеш-таблицу (ассоциативный массив), но чем больше решающих классов я создаю, тем больше памяти он занимает.
То, что я хотел бы сделать, это импортировать файл словаря один раз и передавать его каждому экземпляру решателя по мере необходимости. Но каков наилучший способ сделать это? Должен ли я импортировать словарь в глобальном пространстве, а затем обращаться к нему в классе решателя как globals()['dictionary']? Или я должен импортировать словарь, а затем передать его в качестве аргумента в конструктор класса? Один из них лучше другого? Есть ли третий вариант?
4 ответа
Если вы создаете модуль dictionary.py, содержащий код, который читает файл и создает словарь, этот код будет выполняться только при первом импорте. Дальнейший импорт вернет ссылку на существующий экземпляр модуля. Таким образом, ваши занятия могут:
import dictionary
dictionary.words[whatever]
где dictionary.py имеет:
words = {}
# read file and add to 'words'
Несмотря на то, что на данном этапе это, по сути, единичный случай, применяются обычные аргументы против глобальных переменных. Чтобы найти питон-синглтон-заменитель, найдите объект "borg".
Это действительно единственная разница. Как только объект словаря создан, вы только связываете новые ссылки, когда передаете его, если только вы явно не выполняете глубокое копирование. Имеет смысл, что он создается централизованно один раз и только один раз, если для каждого экземпляра решателя не требуется личная копия для модификации.
Адам, помни это в 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) ]
НТН.
В зависимости от того, что содержит ваш диктант, вас могут заинтересовать модули shelve или anydbm. Они дают вам подобные интерфейсы (просто строки как ключи и элементы для anydbm, строки как ключи и любые объекты python как элементы для shelve), но данные на самом деле находятся в файле DBM (gdbm, ndbm, dbhash, bsddb, в зависимости от того, что доступно на платформе.) Вы, вероятно, все еще хотите разделить фактическую базу данных между классами, как вы просите, но это позволит избежать шага синтаксического анализа текстового файла, а также сохранения его всего в немного памяти.