Хранить самозаполняющийся объект 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)