Ответ 1
Если ваши ключи (необязательно значения) являются строками, стандартный библиотечный модуль shelve делает то, что вы хотите довольно легко.
Итак, я хочу сохранить словарь в постоянном файле. Есть ли способ использовать обычные словарные методы для добавления, печати или удаления записей из словаря в этом файле?
Кажется, что я смогу использовать cPickle для хранения словаря и загрузки его, но я не уверен, где его взять.
Если ваши ключи (необязательно значения) являются строками, стандартный библиотечный модуль shelve делает то, что вы хотите довольно легко.
Отменить из файла при загрузке программы, изменить как обычный словарь в памяти во время работы программы, рассортировать файл, когда программа выходит? Не уверен точно, что еще вы просите здесь.
Как и в ответ Пита, мне нравится использовать JSON, потому что он очень хорошо отображает структуры данных python и очень читаем:
Сохраняющиеся данные тривиальны:
>>> import json
>>> db = {'hello': 123, 'foo': [1,2,3,4,5,6], 'bar': {'a': 0, 'b':9}}
>>> fh = open("db.json", 'w')
>>> json.dump(db, fh)
и загрузка примерно такая же:
>>> import json
>>> fh = open("db.json", 'r')
>>> db = json.load(fh)
>>> db
{'hello': 123, 'bar': {'a': 0, 'b': 9}, 'foo': [1, 2, 3, 4, 5, 6]}
>>> del new_db['foo'][3]
>>> new_db['foo']
[1, 2, 3, 5, 6]
Кроме того, загрузка JSON не страдает теми же проблемами безопасности, что и shelve
и pickle
, хотя IIRC медленнее, чем pickle.
Если вы хотите сохранить на каждой операции, вы можете подклассифицировать объект-диктофон Python:
import os
import json
class DictPersistJSON(dict):
def __init__(self, filename, *args, **kwargs):
self.filename = filename
self._load();
self.update(*args, **kwargs)
def _load(self):
if os.path.isfile(self.filename)
and os.path.getsize(self.filename) > 0:
with open(self.filename, 'r') as fh:
self.update(json.load(fh))
def _dump(self):
with open(self.filename, 'w') as fh:
json.dump(self, fh)
def __getitem__(self, key):
return dict.__getitem__(self, key)
def __setitem__(self, key, val):
dict.__setitem__(self, key, val)
self._dump()
def __repr__(self):
dictrepr = dict.__repr__(self)
return '%s(%s)' % (type(self).__name__, dictrepr)
def update(self, *args, **kwargs):
for k, v in dict(*args, **kwargs).items():
self[k] = v
self._dump()
Что вы можете использовать следующим образом:
db = DictPersistJSON("db.json")
db["foo"] = "bar" # Will trigger a write
Это ужасно неэффективно, но может быстро сбить вас с места.
Предполагая, что ключи и значения имеют рабочие реализации repr
, одним из решений является сохранение строкового представления словаря (repr(dict)
) в файл. Вы можете загрузить его с помощью функции eval
(eval(inputstring)
). Существует два основных недостатка этого метода:
1) Не будет работать с типами, которые имеют неиспользуемую реализацию репрезентации (или могут даже работать, но не работают). Вам нужно будет хотя бы обратить внимание на то, что происходит.
2) Механизм загрузки файлов в основном выполняется с использованием кода Python. Не подходит для безопасности, если вы полностью не контролируете ввод.
У этого есть 1 преимущество: Абсурдно легко сделать.
Мой любимый метод (который не использует стандартные функции словаря python): Чтение/запись файлов YAML с помощью PyYaml. Подробнее см. в этом ответе:
Создайте файл YAML, "employment.yml":
new jersey:
mercer county:
pumbers: 3
programmers: 81
middlesex county:
salesmen: 62
programmers: 81
new york:
queens county:
plumbers: 9
salesmen: 36
Шаг 3: прочитайте его в Python
import yaml
file_handle = open("employment.yml")
my__dictionary = yaml.safe_load(file_handle)
file_handle.close()
и теперь my__dictionary имеет все значения. Если вам нужно сделать это на лету, создайте строку, содержащую YAML, и проанализируйте ее wth yaml.safe_load.
травление имеет один недостаток. это может быть дорого, если ваш словарь должен часто читаться и записываться с диска, и он большой. рассол сбрасывает материал вниз (в целом). unpickle получает вещи вверх (в целом).
если вам приходится обрабатывать небольшие диктофоны, рассол в порядке. Если вы собираетесь работать с чем-то более сложным, идите на berkelydb. В основном это делается для хранения пар ключ: значение.
Если использовать только строки в качестве ключей (как разрешено shelve
), недостаточно, FileDict может быть хорошим способом решить эту проблему.