С Python я могу сохранить постоянный словарь и изменить его?

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

Кажется, что я смогу использовать cPickle для хранения словаря и загрузки его, но я не уверен, где его взять.

Ответ 1

Если ваши ключи (необязательно значения) являются строками, стандартный библиотечный модуль shelve делает то, что вы хотите довольно легко.

Ответ 2

Отменить из файла при загрузке программы, изменить как обычный словарь в памяти во время работы программы, рассортировать файл, когда программа выходит? Не уверен точно, что еще вы просите здесь.

Ответ 3

Использовать JSON

Как и в ответ Пита, мне нравится использовать 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

Это ужасно неэффективно, но может быстро сбить вас с места.

Ответ 4

Предполагая, что ключи и значения имеют рабочие реализации repr, одним из решений является сохранение строкового представления словаря (repr(dict)) в файл. Вы можете загрузить его с помощью функции eval (eval(inputstring)). Существует два основных недостатка этого метода:

1) Не будет работать с типами, которые имеют неиспользуемую реализацию репрезентации (или могут даже работать, но не работают). Вам нужно будет хотя бы обратить внимание на то, что происходит.

2) Механизм загрузки файлов в основном выполняется с использованием кода Python. Не подходит для безопасности, если вы полностью не контролируете ввод.

У этого есть 1 преимущество: Абсурдно легко сделать.

Ответ 5

Мой любимый метод (который не использует стандартные функции словаря 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.

Ответ 6

травление имеет один недостаток. это может быть дорого, если ваш словарь должен часто читаться и записываться с диска, и он большой. рассол сбрасывает материал вниз (в целом). unpickle получает вещи вверх (в целом).

если вам приходится обрабатывать небольшие диктофоны, рассол в порядке. Если вы собираетесь работать с чем-то более сложным, идите на berkelydb. В основном это делается для хранения пар ключ: значение.

Ответ 7

Если использовать только строки в качестве ключей (как разрешено shelve), недостаточно, FileDict может быть хорошим способом решить эту проблему.