събота, 17 януари 2009 г.

Сериализация в Python


„ Програмиране с Python“, ФМИ

Стефан Кънев & Николай Бачийски

11.04.2007г.

Проблем

Имаме нужда да пазим информация между две изпълнения на едно и също приложение. Искаме достъпа до тази информация да е лесен и да добавя минимално код в самото приложение. Нуждите на приложението са прости и няма да имаме нужда от конкурентен достъп или заключване на ресурси.

Решение

Сериализация се нарича възможността да представяме обекти като поредица от байтове. По този начин те могат да бъдат записвани във файловата система или изпращани през TCP/IP и реконструирани в последствие.

Pickle

pickle е модул, който може да сериализира прости Python обекти.

pickle.dump(object, file)
Приема отворен за писане файл file и Python обект object. Записва обекта в файла.
pickle.load(object)
Приема отворен за четене файл и прочита един обект, който е и резултат от функцията

Pickle (2)


from __future__ import with_statement
import pickle

with open('/home/aquarius/foo.txt', 'w') as file:
pickle.dump("The answer", file)
pickle.dump(["spam", "eggs", "ham"], file)

with open('/home/aquarius/foo.txt', 'r') as file:
print pickle.load(file)
print pickle.load(file)

Какво представлява сериализацията?

Pickle сериализира обектите с един от три различни протокола. Протокола по подразбиране представя обектите като ASCII низове. Функциите dumps и loads връщат сериализирана форма вместо да я записват във файл.


import pickle

serializedList = pickle.dumps(["spam", "eggs", "ham"])
print repr(serializedList)
"(lp0\nS'spam'\np1\naS'eggs'\np2\naS'ham'\np3\na."

Какво може да се сериализира?

  • True, False и None
  • int, long, float и complex
  • str и unicode
  • Списъци, речници, множества и n-орки, които съдържат само обекти, които могат да се сериализират
  • Функции и класове, дефинирани в корена на модула
  • Вградени функции, дефинирани в корена на модула

Сериализиране на един обект два пъти

Ако сериализирате сложна структура, в която един обект присъства два пъти (по адрес), pickle ще го сериализира еднократно.


import pickle

primes = [2, 3, 5, 7, 11, 13]
answer = 42
things = [primes, answer, primes]
print things[0] is things[2] # True

serialized = pickle.dumps(things)
newThings = pickle.loads(serialized)
print newThings[0] is newThings[2] # True

print newThings[0] is things[0] # False

Pickler и Unpickler

Имате достъп до същата функционалност под формата на класове.


from __future__ import with_statement
import pickle

with open('/home/aquarius/foo.txt', 'w') as file:
pickler = pickle.Pickler(file)
pickler.dump('Under the Violet Moon')
pickler.dump('Soldier of Fortune')
pickler.dump('Colubrid on the Tree')

with open('/home/aquarius/foo.txt') as file:
unpickler = pickle.Unpickler(file)
print unpickler.load()
print unpickler.load()
print unpickler.load()

cPickle

cPickle e реализация на pickle на C, което я прави доста по-бърза.


from __future__ import with_statement
import cPickle

with open('/home/aquarius/foo.txt', 'w') as file:
cPickle.dump("The answer", file)
cPickle.dump(["spam", "eggs", "ham"], file)

with open('/home/aquarius/foo.txt', 'r') as file:
print cPickle.load(file)
print cPickle.load(file)

cPickle (2)

За сравнение

import pickle
import cPickle
from timeit import Timer

fancy = [[x ** 2 for x in range(0, 1000)], ["spam", "ham", "eggs"],
["-" * i for i in range(0, 1000)],]

def pickleWith(pickler):
serialized = pickler.dumps(fancy)
restored = pickler.loads(serialized)

print "pickle: ", Timer("pickleWith(pickle)", "from __main__ import *").timeit(50)
print "cPickle: ", Timer("pickleWith(cPickle)", "from __main__ import *").timeit(50)

# pickle: 3.28504800797
# cPickle: 0.722439050674

shelve

shelve е сравнително прост модул, който позволява да записвате данни във файл под формата на речник. Можете да ги достъпвате в последствие по ключовете, с които сте ги записали. Всички обекти се сериализират посредством pickle, докато организацията им във файла става посредством dbm, gdbm или berkeley db.

shelve (2)


import shelve

db = shelve.open('/home/aquarius/foo.db')
db['name'] = 'Mityo the Python'
db['age'] = 33
db['favouriteBands'] = ["Blackmore's Night", "Deep Purple", "Rainbow"]
db['favouriteSong'] = "Colubrid on the Tree"
db.close()

db = shelve.open('/home/aquarius/foo.db')
print db.keys()
print db['name']
print db['favouriteBands']
print db['favouriteSong']
db.close()

Няма коментари:

Публикуване на коментар