2013-11-07 1 views
0

Я сохраняю вызов класса Задача в массиве в .dat-файле. Я хотел бы прочитать этот файл и восстановить вызовы класса.Как удалить кавычки из инициализатора класса при чтении из файла. Python

Вот класс, который я использую прямо сейчас:

class Task: 

    def __init__(self, name, timespent): 
     self.name = name 
     self.timespent = timespent 

    def __repr__(self): 
     return repr('Task("%s",%s)'%(self.name, self.timespent)) 

Вот чтение из файла:

task_list = [] 
with open("task_list2.dat", "r") as file: 
    task_list = eval(file.readline()) 

Вот запись в файл:

with open("task_list2.dat", "w") as outFile: 
    print(repr(task_list), file = outFile) 

И вот содержание файла: ['Task("class",20)'] Где «класс» - это имя задачи.

Я понимаю, что проблема связана с одиночными кавычками вокруг «Задача (« класс », 20)», но я не знаю, как избавиться от них. Сообщение об ошибке, которое я получаю, говорит что-то в строках: «str-объект не имеет атрибута« name »

Как удалить эти кавычки, чтобы я мог восстановить классы в следующий раз, когда я прочитал файл?

+0

Удалите исходные кавычки в своей функции 'repr'. – SevenBits

+1

Мне любопытно, вместо того, чтобы угадать, что находится в файле (что очень опасно, если кто-то, где заменить содержимое вашего файла вредоносным кодом), почему бы не сохранить задачу, которую нужно выполнить/аргументы как JSON, и проанализировать это? –

+0

@MikeMcMahon: Проблема с JSON заключается в том, что это не полный сериализатор для чего-либо, кроме float, bool, unicode, NoneType, а списки и dicts составляют рекурсивно из вышеперечисленного. В частности, если вы хотите сериализовать объекты своих собственных классов, вам нужно написать сериализатор поверх него. Использование pickle, YAML, jsonpickle или другого формата, который обрабатывает пользовательские типы, означает, что вам не нужно это делать. – abarnert

ответ

5

You really, really, really don't want to try to use repr and eval as a serialization format.

Если вы просто использовали, скажем, pickle, вы бы не эта проблема вообще:

with open("task_list2.dat", "wb") as outFile: 
    pickle.dump(task_list, outFile) 

with open("task_list2.dat", "rb") as file: 
    task_list = pickle.load(file) 

Намного проще, да?


Но если вы хотите знать, как решить непосредственную проблему вместо того, чтобы это не имеет значения: У вас есть несколько проблем в вашем методе __repr__, все из которых должны быть исправлены, если вы хотите, чтобы быть круглым -trippable.

  • Вы создаете строковое представление ... и затем вызываете на нем repr. Вы хотите вернуть строковое представление, а не строковое представление из представление строки. Просто оставьте в стороне repr.
  • Вы должны всегда делегировать repr подэлементов, а не str. Если вы используете % -formatting, это означает использование %r, а не %s.
  • Не пытайтесь добавлять котировки вокруг вещей. Это может случиться, если сам объект не имеет кавычек, обратных косых черт, невидимых символов и т. Д., Но зачем полагаться на это? Если вы считаете, что вам нужны цитаты, это почти всегда признак того, что вы нарушили предыдущее правило, и вы должны исправить это.

Вот как вы можете написать круглодонную trippable магнезии для этого класса:

def __repr__(self): 
    return 'Task(%r, %r)' % (self.name, self.timespent)) 

И вы можете убедиться в том, что он делает то, что вы хотите:

>>> t = Task('task name', 23.4) 
>>> t 
Task('task name', 23.4) 
>>> eval(repr(t)) 
Task('task name', 23.4) 

Конечно в вашем конкретном примере, только исправление первой проблемы (удаление ложного вызова до repr) избаловало бы от одиночных кавычек и сделало бы это lar пример работы. Вы также можете взломать это на стороне чтения, дважды позвонив eval. Или, для этого конкретного примера, даже позвонив по номеру eval(s[1:-1]) или eval(s.strip("'")). Но любое «исправление», подобное этому, просто затруднит отладку общих проблем, с которыми вы столкнетесь, когда у вас есть, например, имя, которое не так просто, как одно целое буквенное слово ASCII.

+0

Я никогда не слышал о мариновании. Спасибо за это и спасибо за двойной ответ! –