Новичок в Python (программирование) и хранилище данных

#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:

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

Смотрите: http://docs.python.org/tutorial/inputoutput.html

Комментарии:

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.