Уведомления

Группа в Telegram: @pythonsu

#1 Ноя. 1, 2008 01:37:13

shiza
От:
Зарегистрирован: 2007-07-03
Сообщения: 1073
Репутация: +  0  -
Профиль   Отправить e-mail  

тонкости pickle

Хочу передать объект с одного компьютера на другой =)
Но, оказывается все не так просто. Вот пример.

Сохраняем объект:

import pickle

class O(object):
def __init__(self):
a1 = 0
o = O()

p = pickle.dumps(o, 2)

file('dump', 'wb').write(p)
Пытаемся загрузить объект:
import pickle

p = file('dump', 'rb').read()
o = pickle.loads(p)
print o.a1
Получается такой трейс:
Traceback (most recent call last):
File "C:\tmp5\\load.py", line 4, in <module>
o = pickle.loads(p)
File "C:\Python25\lib\pickle.py", line 1374, in loads
return Unpickler(file).load()
File "C:\Python25\lib\pickle.py", line 858, in load
dispatch[key](self)
File "C:\Python25\lib\pickle.py", line 1090, in load_global
klass = self.find_class(module, name)
File "C:\Python25\lib\pickle.py", line 1126, in find_class
klass = getattr(mod, name)
AttributeError: 'module' object has no attribute 'O'
Как-бы это обойти наименьшей кровью? =)



Отредактировано (Ноя. 1, 2008 01:37:28)

Офлайн

#2 Ноя. 1, 2008 02:16:51

bw
От:
Зарегистрирован: 2007-09-26
Сообщения: 938
Репутация: +  20  -
Профиль   Адрес электронной почты  

тонкости pickle

> AttributeError: ‘module’ object has no attribute ‘O’
Естественно, ведь этого объекта нет в модуле-потребителе. Pickle сохраняет состояние экземпляра объекта, а не класс со всеми его методами целиком. Что бы выполнить десериализацию pickle должен иметь доступ к этому классу.
В качестве решения - вынеси описание класса O в отдельный модуль и гарантируй что на обоих концах (поставщик и потребитель) будут иметь доступ к нему. Самый естественный, пожалуй, метод для этого это использовать один и тот же пакет, в котором заключается описание класса O. Другими словами - получатель обязательно должен знать тип объекта, который ему передают.

..bw



Офлайн

#3 Ноя. 1, 2008 02:45:25

shiza
От:
Зарегистрирован: 2007-07-03
Сообщения: 1073
Репутация: +  0  -
Профиль   Отправить e-mail  

тонкости pickle

Я надеялся на Магию, что есть какие-то механизмы для этого. ;)

bw
Самый естественный, пожалуй, метод для этого это использовать один и тот же пакет, в котором заключается описание класса O.
Это довольно сложно из-за того что надо будет эти пакеты (изменения в них) как-то синхронизировать.
Получается, придется делать какое-то общее хранилеще модулей и оттуда их подгружать. Прям целый огород.



Отредактировано (Ноя. 1, 2008 02:46:02)

Офлайн

#4 Ноя. 1, 2008 04:27:35

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

тонкости pickle

Чудак-человек. Сохранить класс вместе с объектом технически не сложно (но очень накладно по памяти) - а толку чуть. Все равно нужна синхронизация - дело особое, трудоемкое и специфическое. Интересно послушать, как, по предположениям, должна была бы работать инмверсальная “Магия” на, к примеру, двух даже не имеющих доступа к тернету машинах?
Или питон в добавок ко всему имеет еще одно революционное новшество - телепатический языко-зависимый канал общения, поставляющийся с дистрибутивом? :)



Офлайн

#5 Ноя. 1, 2008 04:31:58

bw
От:
Зарегистрирован: 2007-09-26
Сообщения: 938
Репутация: +  20  -
Профиль   Адрес электронной почты  

тонкости pickle

Ну или передавать модуль (исходник) с объектом O потребителю. Тот его компилирует (не обязательно записывать этот исходник на винт, что бы он заработал, всё можно выполнить в мозге, сохранить можно байт-код в любом удобном для тебя виде, например в РСУБД :-), прописывает в sys.modules и т.п.

Для компиляции в байт-код: встроенный метод compile.
Для сериализации и десериализации полученного объекта: модуль marshal.
Для создания нового модуля: метод module модуля new.

Вот небольшой пример (сериализацию кода я не буду делать, это очень просто и не интересно):

>>> import sys, new
>>> source = """def bar():
... print '"bar" method of "%s" module'%__name__"""
>>> code = compile(source, 'foo', 'exec')
>>> module = new.module('foo')
>>> exec code in module.__dict__
>>> module.bar()
"bar" method of "foo" module
>>> sys.modules['foo'] = module
>>> import foo
>>> foo.bar()
"bar" method of "foo" module
Элементарно, Ватсон :-).
Компиляцию кода стоит делать именно на целевой машине, а не на поставщике этого кода. Ибо, возможно, будут разные платформы, например, разные версии Python.

p.s. Никто не знает, когда появится подсветка кода и будет использоваться шрифт с фиксированной шириной?

..bw



Отредактировано (Ноя. 1, 2008 04:34:03)

Офлайн

#6 Ноя. 1, 2008 12:14:22

shiza
От:
Зарегистрирован: 2007-07-03
Сообщения: 1073
Репутация: +  0  -
Профиль   Отправить e-mail  

тонкости pickle

Андрей Светлов
Интересно послушать, как, по предположениям, должна была бы работать инмверсальная “Магия” на, к примеру, двух даже не имеющих доступа к тернету машинах?
Или питон в добавок ко всему имеет еще одно революционное новшество - телепатический языко-зависимый канал общения, поставляющийся с дистрибутивом? :)
Pickle же определяет зависимые объекты, и даже циклические ссылки.
Почемуб ему не обрабатывать и описание класса? Если на сам, то хоть с подсказкой. %)



Отредактировано (Ноя. 1, 2008 12:15:38)

Офлайн

#7 Ноя. 1, 2008 23:31:48

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

тонкости pickle

bwНе так-то все элементарно: после этого шага проблемы только начинаются. Возможно, модуль имеет зависимости - прийдется тащить еще и их. Захочется кешировать полученные результаты - чтобы проталкивать модули через сеть только один раз. Чтобы правильно все работало - следует передавать еще и версии модулей/объектов. Версии появятся разные на prodaction - к гадалке не ходи. Один клиент обновил просрамму, второй еще нет.
Так что, с моей точки зрения, проблема все же комплексная и не совсем простая. Хоть и решаемая, конечно же.



Офлайн

#8 Ноя. 2, 2008 02:28:48

shiza
От:
Зарегистрирован: 2007-07-03
Сообщения: 1073
Репутация: +  0  -
Профиль   Отправить e-mail  

тонкости pickle

В принципе у меня уже есть механизм, который делает импорт всех модулей из базы данных.
У импорта уже есть кеширование.
Но может есть другие варианты?



Офлайн

#9 Ноя. 2, 2008 05:15:40

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

тонкости pickle

Эээ. Если приложения настолько близко, что могут разделять одну СУБД - тогда зачем вообще огород городить? Использовать ее, и дело с концом…



Офлайн

#10 Ноя. 6, 2008 14:58:09

shiza
От:
Зарегистрирован: 2007-07-03
Сообщения: 1073
Репутация: +  0  -
Профиль   Отправить e-mail  

тонкости pickle

Решил огород не городить и позвал Оккама с бритвой:
не использую больше классы, как контейнеры для данных, а использую словари. Они пиклятся хорошо без выкрутасов =)



Отредактировано (Ноя. 6, 2008 14:58:33)

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version