С Python я могу сохранить постоянный словарь и изменить его? - PullRequest
11 голосов
/ 04 августа 2009

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

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

Ответы [ 7 ]

18 голосов
/ 04 августа 2009

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

7 голосов
/ 17 апреля 2014

Использовать 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-объекта dict:

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

Что крайне неэффективно, но может быстро оторвать вас от земли.

5 голосов
/ 04 августа 2009

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

1 голос
/ 04 августа 2009

Мой любимый метод (в котором не используются стандартные функции словаря Python): чтение / запись файлов YAML с использованием PyYaml . Подробности см. В этом ответе , кратко здесь:

Создайте файл YAML, "jobs.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, и проанализируйте ее с помощью yaml.safe_load.

1 голос
/ 04 августа 2009

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

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

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

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

0 голосов
/ 21 августа 2012

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

0 голосов
/ 04 августа 2009
У травления

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

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

...