#python #python-3.x
#python #python-3.x
Вопрос:
У меня вопрос о хранилище данных. У меня есть программа, которая создает список объектов. Каков наилучший способ сохранить их в файле, чтобы программа могла перезагрузить их позже? Я пытался использовать Pickle, но мне кажется, что я, возможно, направляюсь не по тому пути, и я продолжаю получать эту ошибку при попытке считывания данных:
Traceback (most recent call last):
File "test.py", line 110, in <module>
knowledge = pickle.load(open("data.txt"))
File "/sw/lib/python3.1/pickle.py", line 1356, in load
encoding=encoding, errors=errors).load()
File "/sw/lib/python3.1/codecs.py", line 300, in decode
(result, consumed) = self._buffer_decode(data, self.errors, final)
UnicodeDecodeError: 'utf8' codec can't decode byte 0x80 in position 0: invalid start byte
Отредактировано для добавления: вот немного кода, который я пытаюсь:
FILE = open("data.txt", "rb")
knowledge = pickle.load(open("data.txt"))
FILE = open("data.txt", 'wb')
pickle.dump(knowledge, FILE)
Комментарии:
1. Какая версия Python? Как вы создали файл?
2. Повторите обработку. Внимательно прочитайте документацию! Опубликуйте здесь немного кода, и мы поможем вам найти, что не так :). Вы также могли бы использовать JSON, для этого есть несколько модулей.
Ответ №1:
Я думаю, проблема в том, что строка
knowledge = pickle.load(open("data.txt"))
не открывает файл в двоичном режиме. Python 3.2:
>>> import pickle
>>>
>>> knowledge = {1:2, "fred": 19.3}
>>>
>>> with open("data.txt", 'wb') as FILE:
... pickle.dump(knowledge, FILE)
...
>>> knowledge2 = pickle.load(open("data.txt"))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.2/lib/python3.2/codecs.py", line 300, in decode
(result, consumed) = self._buffer_decode(data, self.errors, final)
UnicodeDecodeError: 'utf8' codec can't decode byte 0x80 in position 0: invalid start byte
>>> knowledge2 = pickle.load(open("data.txt","rb"))
>>> knowledge2
{1: 2, 'fred': 19.3}
Ответ №2:
Нет необходимости переписывать shelve, библиотеку сохранения объектов Python. Пример:
import shelve
d = shelve.open(filename) # open -- file may get suffix added by low-level
# library
d[key] = data # store data at key (overwrites old data if
# using an existing key)
data = d[key] # retrieve a COPY of data at key (raise KeyError if no
# such key)
del d[key] # delete data stored at key (raises KeyError
# if no such key)
flag = d.has_key(key) # true if the key exists
klist = d.keys() # a list of all existing keys (slow!)
# as d was opened WITHOUT writeback=True, beware:
d['xx'] = range(4) # this works as expected, but...
d['xx'].append(5) # *this doesn't!* -- d['xx'] is STILL range(4)!
# having opened d without writeback=True, you need to code carefully:
temp = d['xx'] # extracts the copy
temp.append(5) # mutates the copy
d['xx'] = temp # stores the copy right back, to persist it
# or, d=shelve.open(filename,writeback=True) would let you just code
# d['xx'].append(5) and have it work as expected, BUT it would also
# consume more memory and make the d.close() operation slower.
d.close() # close it
Ответ №3:
Если вы просто хотите воссоздать некоторые объекты класса позже, самым простым решением было бы поместить их свойства в файл, и они будут считывать их обратно, создавая объекты на основе содержимого.
Комментарии:
1. Нет, это непросто. Это требует много дополнительного ввода и нарушает DRY (и, следовательно, также несет в себе риск нарушения синхронизации).
2. Структура данных довольно сложная. Статья, на которую вы ссылаетесь, не рекомендует выполнять in вручную и предлагает pickle. У вас есть какие-либо идеи, что может быть причиной моей ошибки?
Ответ №4:
Вы можете использовать cPickle или Picke, это не имеет значения. Откройте в двоичном режиме (rb) и попробуйте установить для протокола значение -1.
Попробуйте что-то вроде этого:
import cPickle
my_file= open('wohoo.file', 'wb')
largeObject= Magic() #insert your logic here
cPickle.dump(largeObject, my_file, -1)
my_file.close()
other_file = open('wohoo.file', 'rb')
welcomeBack - cPickle.load(other_file )
other_file.close()
Комментарии:
1. -1 Доказуемо неверно, прочитайте еще раз. Он действительно находит файл. Он даже может это прочитать. Не удается только декодировать его в кодировку, которую предпочитает Python.