Хранить самозаполняющийся объект Python в удобочитаемом файле

Я унаследовал сценарий Python, который собирает людей, готовящих торт для офиса каждую неделю. При этом он ведет список людей, которые хотят сделать торт, а также их адреса электронной почты, последний раз, когда они делали торт, и некоторые другие вещи. Он хранит их все в самозаполняющемся объекте, показанном ниже:

import datetime as dt
import pickle

class Person():
    name_list=[]
    def __init__(self,name,email):
        self.name=name
        self.email=email
        self.lastCake=dt.datetime.strptime('01011990', '%d%m%Y').date()
        self.weight=0
        self.update_weight()
        Person.name_list.append(self)

    def __repr__(self):
        return "%s: %i"%(self.name,self.weight)

    def __str__(self):
        return "%s: %i"%(self.name,self.weight)

    def __lt__(self,other):
        return self.weight < other.weight

    def update_weight(self,now=dt.date.today()):
        days_since_cake=now-self.lastCake
        self.weight=int(days_since_cake.days)

def make_cake_list():
    Person('Alice','FAKE@FAKE.com')
    Person('Bob','FAKE@FAKE.com')
    Person('Cath','FAKE@FAKE.com')
    Person('Dave','FAKE@FAKE.com')

Поскольку этот сценарий отслеживает и отправляет / получает электронную почту, он работает постоянно и, таким образом, иногда отключается при перезагрузке системы / сбоях питания / сбоях. Это означает, что объект Person записывается / читается в / из файла, и Pickle используется для этого с двумя функциями:

def save_cake_list(people):
    with open("cake_list.dat",'w') as f:
        pickle.dump(people,f)

def read_cake_list():
    with open("cake_list.dat",'r') as f:
        return pickle.load(f)

Все довольно стандартно. За исключением того, как он настроен и как он поддерживает свои списки, это настоящая свинья для добавления новых людей, а затем для отслеживания того, кого вы добавили (некоторые имена жестко закодированы, но я хочу избавиться от этой функции. Чем реже мне приходится копаться в кишках сценария, тем лучше!). И с Pickle, человек не может читать / редактировать файл, который он создает.

Итак, есть ли способ взять объект Персона (и его самое важное, самозаполняющееся? name_list) и передать его в удобочитаемый файл? На ум приходят XML-файлы, но методы, на которые я смотрел, похоже, не справляются с системой самозаполняющихся списков, которую я имею здесь, и у меня нет большого опыта с ними.

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

Мысли?

РЕДАКТИРОВАТЬ: я не верю, что это то же самое, что вопрос "Словарь в последовательный словарь" в другом месте, так как я думаю, что преобразование моего класса в словарь потеряло бы ключевую часть функциональности, необходимой в другом месте кода.

Однако я не знаком со словарями, поэтому, если я не прав, предоставьте MWS и объясните, почему словари будут работать.

1 ответ

Я бы пошел с json как формат для хранения данных. Тогда вы можете воспользоваться веб-решениями, если это необходимо. Вы можете пойти с json модуль, но это потребует нескольких хуков, поэтому я выберу самый простой вариант. Я взял jsonpickle для сериализации и десериализации сложных объектов Python. Вот пример

import datetime as dt
import jsonpickle

class Person():
    name_list=[]
    def __init__(self,name,email):
        self.name=name
        self.email=email
        self.lastCake=dt.datetime.strptime('01011990', '%d%m%Y').date()
        self.weight=0
        self.update_weight()
        Person.name_list.append(self)

    def default(self):
        return self.__dict__

    def __repr__(self):
        return "%s: %i"%(self.name,self.weight)

    def __str__(self):
        return "%s: %i"%(self.name,self.weight)

    def __lt__(self,other):
        return self.weight < other.weight

    def update_weight(self,now=dt.date.today()):
        days_since_cake=now-self.lastCake
        self.weight=int(days_since_cake.days)

def make_cake_list():
    persons = list()
    persons.append(Person('Alice','FAKE@FAKE.com'))
    persons.append(Person('Bob','FAKE@FAKE.com'))
    persons.append(Person('Cath','FAKE@FAKE.com'))
    persons.append(Person('Dave','FAKE@FAKE.com'))
    return persons

persons = make_cake_list()
print jsonpickle.encode(persons, unpicklable=False)
Другие вопросы по тегам