2010-01-30 1 views
8

Чтобы избежать неоднократного доступа к SOAP-серверу во время разработки, я пытаюсь кэшировать результаты, чтобы я мог запускать остальную часть своего кода без запроса сервера каждый раз.Как я могу замачивать результаты пенообразования?

С помощью приведенного ниже кода я получаю PicklingError: Can't pickle <class suds.sudsobject.AdvertiserSearchResponse at 0x03424060>: it's not found as suds.sudsobject.AdvertiserSearchResponse, когда я пытаюсь разжевать результат пенообразования. Я думаю, это потому, что классы динамически создаются.

import pickle 
from suds.client import Client 

client = Client(...) 
result = client.service.search(...) 

file = open('test_pickle.dat', 'wb') 
pickle.dump(result, file, -1) 
file.close() 

Если я бросаю версию на -1 протокол от pickle.dump(result, file, -1), я получаю другую ошибку:

TypeError: a class that defines __slots__ without defining __getstate__ cannot be pickled 

ли травление правильно делать? Могу ли я заставить его работать? Есть ли способ лучше?

ответ

8

В сообщении об ошибке вы в настоящее время становится все пытается сказать вам, что вы пытаетесь замариновать экземпляры, которые не пригодны для консервирования (в древнем протоколе наследство маринад вы теперь используете), потому что их класс определяет __slots__ но не метод __getstate__.

Однако, даже изменение их класса не помогло бы, потому что тогда вы столкнулись с проблемой , которую вы уже правильно определили как вероятную из-за динамически генерируемых классов. Все протоколы pickle сериализуют классы (и функции) «по имени», что существенно ограничивает их именами верхнего уровня в своих модулях. И, сериализуя экземпляр, абсолютно , требует сериализации класса (как еще вы могли бы восстановить экземпляр позже, если класс не был вокруг ?!).

Таким образом, вам нужно будет сохранить и перезагрузить свои данные каким-либо другим способом, нарушив текущую прямую зависимость от конкретных классов в suds.sudsobject в пользу в зависимости от интерфейса (формализованного или только определенного путем утиной печати), который может быть реализованные как с помощью таких конкретных классов, когда вы фактически получаете доступ к SOAP-серверу, либо более простые «домашние», когда вы загружаете данные из файла. (Данные, представляющие состояние экземпляра, без сомнения, могут быть представлены как dict, поэтому вы можете заставить его с помощью рассола, если хотите, например, через модуль copy_reg, который позволяет настраивать протоколы сериализации/десериализации для объектов, которые вы вынуждены обрабатывать неинвазивно [[поэтому вы не можете обойти добавление __getstate__ или тому подобное к их классам]] - проблема будет возникать только в том случае, если среди таких объектов есть богатая сетка взаимных ссылок).

+1

Есть ли способ получить определение динамически созданного класса, чтобы его можно было сохранить в файл, а затем использовать как обычный класс? – tponthieux

2

Вы сами собираете объект класса, а не объекты экземпляра класса. Это не будет работать, если объект класса будет воссоздан. Тем не менее, трассировка экземпляров класса будет работать до тех пор, пока объект класса существует.

+0

Я думаю, что я следую тому, что вы говорите, но, проверив, введите (результат) и result .__ class__ is , так что я не пытаюсь рассолить экземпляр? – Mat

+0

Из вставленного кода кажется, что вы собираете экземпляр, но ошибка, о которой вы говорите, предполагает, что вы травляете класс. –

+0

Хорошо, я не собираюсь полностью гаснуть, тогда :) Я получаю другую ошибку, если я отброшу -1 для последнего протокола, который я поправлю на вопрос, чтобы включить, если он потеряет больше света. – Mat

Смежные вопросы