Как я могу засолить результаты пены? - PullRequest
8 голосов
/ 30 января 2010

Чтобы избежать повторного доступа к серверу 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

Травление - это то, что нужно делать? Могу ли я заставить его работать? Есть ли лучший способ?

Ответы [ 2 ]

8 голосов
/ 30 января 2010

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

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

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

2 голосов
/ 30 января 2010

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

...