Форум сайта python.su
Хочу передать объект с одного компьютера на другой =)
Но, оказывается все не так просто. Вот пример.
Сохраняем объект:
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)
Офлайн
> AttributeError: ‘module’ object has no attribute ‘O’
Естественно, ведь этого объекта нет в модуле-потребителе. Pickle сохраняет состояние экземпляра объекта, а не класс со всеми его методами целиком. Что бы выполнить десериализацию pickle должен иметь доступ к этому классу.
В качестве решения - вынеси описание класса O в отдельный модуль и гарантируй что на обоих концах (поставщик и потребитель) будут иметь доступ к нему. Самый естественный, пожалуй, метод для этого это использовать один и тот же пакет, в котором заключается описание класса O. Другими словами - получатель обязательно должен знать тип объекта, который ему передают.
..bw
Офлайн
Я надеялся на Магию, что есть какие-то механизмы для этого. ;)
bwЭто довольно сложно из-за того что надо будет эти пакеты (изменения в них) как-то синхронизировать.
Самый естественный, пожалуй, метод для этого это использовать один и тот же пакет, в котором заключается описание класса O.
Отредактировано (Ноя. 1, 2008 02:46:02)
Офлайн
Чудак-человек. Сохранить класс вместе с объектом технически не сложно (но очень накладно по памяти) - а толку чуть. Все равно нужна синхронизация - дело особое, трудоемкое и специфическое. Интересно послушать, как, по предположениям, должна была бы работать инмверсальная “Магия” на, к примеру, двух даже не имеющих доступа к тернету машинах?
Или питон в добавок ко всему имеет еще одно революционное новшество - телепатический языко-зависимый канал общения, поставляющийся с дистрибутивом? :)
Офлайн
Ну или передавать модуль (исходник) с объектом 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
Отредактировано (Ноя. 1, 2008 04:34:03)
Офлайн
Андрей СветловPickle же определяет зависимые объекты, и даже циклические ссылки.
Интересно послушать, как, по предположениям, должна была бы работать инмверсальная “Магия” на, к примеру, двух даже не имеющих доступа к тернету машинах?
Или питон в добавок ко всему имеет еще одно революционное новшество - телепатический языко-зависимый канал общения, поставляющийся с дистрибутивом? :)
Отредактировано (Ноя. 1, 2008 12:15:38)
Офлайн
bwНе так-то все элементарно: после этого шага проблемы только начинаются. Возможно, модуль имеет зависимости - прийдется тащить еще и их. Захочется кешировать полученные результаты - чтобы проталкивать модули через сеть только один раз. Чтобы правильно все работало - следует передавать еще и версии модулей/объектов. Версии появятся разные на prodaction - к гадалке не ходи. Один клиент обновил просрамму, второй еще нет.
Так что, с моей точки зрения, проблема все же комплексная и не совсем простая. Хоть и решаемая, конечно же.
Офлайн
В принципе у меня уже есть механизм, который делает импорт всех модулей из базы данных.
У импорта уже есть кеширование.
Но может есть другие варианты?
Офлайн
Эээ. Если приложения настолько близко, что могут разделять одну СУБД - тогда зачем вообще огород городить? Использовать ее, и дело с концом…
Офлайн
Решил огород не городить и позвал Оккама с бритвой:
не использую больше классы, как контейнеры для данных, а использую словари. Они пиклятся хорошо без выкрутасов =)
Отредактировано (Ноя. 6, 2008 14:58:33)
Офлайн