Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/336.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在python中序列化suds对象_Python_Soap_Pickle_Suds - Fatal编程技术网

在python中序列化suds对象

在python中序列化suds对象,python,soap,pickle,suds,Python,Soap,Pickle,Suds,好的,我正在努力让python变得更好,所以我不确定这是否是我开始做的正确方法,但这是我当前的问题 我需要通过SOAP方法获取一些信息,现在只使用部分信息,但存储整个结果以备将来使用(我们需要尽可能少地使用服务)。查找访问该服务的最佳方式时,我认为suds是一个不错的选择,它很简单,获取数据很有魅力。但现在我想以某种方式保存结果,最好是序列化/保存在数据库中,以便以后可以将其取出并使用相同的结果 最好的方法是什么,看起来pickle/json不是一个选项?谢谢 更新 阅读顶部的答案可以让我更好地

好的,我正在努力让python变得更好,所以我不确定这是否是我开始做的正确方法,但这是我当前的问题

我需要通过SOAP方法获取一些信息,现在只使用部分信息,但存储整个结果以备将来使用(我们需要尽可能少地使用服务)。查找访问该服务的最佳方式时,我认为suds是一个不错的选择,它很简单,获取数据很有魅力。但现在我想以某种方式保存结果,最好是序列化/保存在数据库中,以便以后可以将其取出并使用相同的结果

最好的方法是什么,看起来pickle/json不是一个选项?谢谢

更新
阅读顶部的答案可以让我更好地理解为什么这不是一个选项,我想我无法用我需要的信息重新创建一个基本对象?

是的,我确认了我在您提到的答案中给出的解释——动态生成的类不容易选择(也不容易序列化),您需要提取所有状态信息,对该状态进行pickle处理,并在检索时重建棘手的sudsobject(如果您确实坚持使用它;-)

我为sud的objectintance实现了一个虚拟类,然后能够序列化。FakeSudsInstance的行为类似于原始的Suds对象实例,请参见以下内容:

from suds.sudsobject import Object as SudsObject

class FakeSudsNode(SudsObject):

    def __init__(self, data):
        SudsObject.__init__(self)
        self.__keylist__ = data.keys()
        for key, value in data.items():
            if isinstance(value, dict):
                setattr(self, key, FakeSudsNode(value))
            elif isinstance(value, list):
                l = []
                for v in value:
                    if isinstance(v, list) or isinstance(v, dict):
                        l.append(FakeSudsNode(v))
                    else:
                        l.append(v)
                setattr(self, key, l)
            else:
                setattr(self, key, value)


class FakeSudsInstance(SudsObject):

    def __init__(self, data):
        SudsObject.__init__(self)
        self.__keylist__ = data.keys()
        for key, value in data.items():
            if isinstance(value, dict):
                setattr(self, key, FakeSudsNode(value))
            else:
                setattr(self, key, value)

    @classmethod
    def build_instance(cls, instance):
        suds_data = {}
        def node_to_dict(node, node_data):
            if hasattr(node, '__keylist__'):
                keys = node.__keylist__
                for key in keys:
                    if isinstance(node[key], list):
                        lkey = key.replace('[]', '')
                        node_data[lkey] = node_to_dict(node[key], [])
                    elif hasattr(node[key], '__keylist__'):
                        node_data[key] = node_to_dict(node[key], {})
                    else:
                        if isinstance(node_data, list):
                            node_data.append(node[key])
                        else:
                            node_data[key] = node[key]
                return node_data
            else:
                if isinstance(node, list):
                    for lnode in node:
                        node_data.append(node_to_dict(lnode, {}))
                    return node_data
                else:
                    return node
        node_to_dict(instance, suds_data)
        return cls(suds_data)
现在,在一次肥皂水通话后,例如:

# Now, after a suds call, for example below
>>> import cPickle as pickle
>>> suds_intance = client.service.SomeCall(account, param)
>>> fake_suds = FakeSudsInstance.build_instance(suds_intance)
>>> dumped = pickle.dumps(fake_suds)
>>> loaded = pickle.loads(dumped)

我希望它能有所帮助。

我一直在使用以下方法将Suds对象转换为JSON:

from suds.sudsobject import asdict

def recursive_asdict(d):
    """Convert Suds object into serializable format."""
    out = {}
    for k, v in asdict(d).iteritems():
        if hasattr(v, '__keylist__'):
            out[k] = recursive_asdict(v)
        elif isinstance(v, list):
            out[k] = []
            for item in v:
                if hasattr(item, '__keylist__'):
                    out[k].append(recursive_asdict(item))
                else:
                    out[k].append(item)
        else:
            out[k] = v
    return out

def suds_to_json(data):
    return json.dumps(recursive_asdict(data))

我更新了
recursive\u asdict
示例,使其与python3兼容(
items
,而不是
iteritems


这是我在研究和找到这个答案之前想到的。这实际上对我处理复杂的肥皂水响应和其他对象(如
\uuu内置\uuuu
)很有效,因为该解决方案不受肥皂水的影响:

import datetime

def object_to_dict(obj):
    if isinstance(obj, (str, unicode, bool, int, long, float, datetime.datetime, datetime.date, datetime.time)):
        return obj
    data_dict = {}
    try:
        all_keys = obj.__dict__.keys()  # vars(obj).keys()
    except AttributeError:
        return obj
    fields = [k for k in all_keys if not k.startswith('_')]
    for field in fields:
        val = getattr(obj, field)
        if isinstance(val, (list, tuple)):
            data_dict[field] = []
            for item in val:
                data_dict[field].append(object_to_dict(item))
        else:
            data_dict[field] = object_to_dict(val)
    return data_dict
这个解决方案有效,而且实际上速度更快。它也适用于不具有
\uuuuu键列表\uuuu
属性的对象

我在一个复杂的suds输出对象上运行了100次基准测试,这个解决方案的运行时间是0.04到0.052秒(平均0.045724287)。而上面的递归asdict解决方案运行了0.082到0.102秒,几乎是原来的两倍(平均0.0829765582)

然后,我回到绘图板,重新执行该函数以获得更高的性能,它不需要
datetime
导入。我利用了
\uuuuuuuuuu键列表
属性,因此这对其他对象(如
\uuuuuu内置项
)不起作用,但对suds对象输出效果很好:

def fastest_object_to_dict(obj):
    if not hasattr(obj, '__keylist__'):
        return obj
    data = {}
    fields = obj.__keylist__
    for field in fields:
        val = getattr(obj, field)
        if isinstance(val, list):  # tuple not used
            data[field] = []
            for item in val:
                data[field].append(fastest_object_to_dict(item))
        else:
            data[field] = fastest_object_to_dict(val)
    return data

运行时间为0.18-0.033秒(平均0.0260889721秒),比
递归asdict
解决方案快了近4倍。

以上建议的解决方案丢失了有关类名的宝贵信息-在DFP client之类的一些库中可能很有价值,因为实体类型可能被编码为动态生成的类名(即模板创意/图像创意

下面是我使用的解决方案,它可以保留类名并恢复dict序列化对象,而不会丢失数据(除了suds.sax.text.text,它将被转换为常规unicode对象,也可能是我没有遇到过的其他类型)


我正在使用'retxml=True'选项来获取原始结果,然后将其转换为dict(应该是可序列化的)现在-看起来它可以工作了…谢谢!@pssdbt,太好了-或者您可以序列化XML本身,但是我相信取消勾选pickle dict会比解析XML更快,所以我认为您做出了正确的选择。
node\u data.append(node\u to\u dict(lnode,{}))
是错误的,因为它将dict传递到node_to_dict。
返回node_data
如果hasattr(node,'.\u keylist_uu'):也应该返回FakeSudsNode(node_data),因为它构成dict。请注意,该函数不能与suds对象列表一起工作。这可以通过
[递归的asdict(d)来解决]
@Jon它确实可以工作,因为
elif isinstance(v,list)
检查。要指出的是,对于Python 3,用items()替换iteritems()。谢谢你的回答!我只需要
dict2suds
部分,在
out.pop(“\u class\uuuuuuuuuu”)中有一个错误
零件,但将其卸下并直接替换为
.object(dict=out)
修复了我的案例。感谢您的提示!
def fastest_object_to_dict(obj):
    if not hasattr(obj, '__keylist__'):
        return obj
    data = {}
    fields = obj.__keylist__
    for field in fields:
        val = getattr(obj, field)
        if isinstance(val, list):  # tuple not used
            data[field] = []
            for item in val:
                data[field].append(fastest_object_to_dict(item))
        else:
            data[field] = fastest_object_to_dict(val)
    return data
from suds.sudsobject import asdict, Factory as SudsFactory

def suds2dict(d):                                                               
    """                                                                         
    Suds object serializer 
    Borrowed from https://stackoverflow.com/questions/2412486/serializing-a-suds-object-in-python/15678861#15678861                                                     
    """                                                                         
    out = {'__class__': d.__class__.__name__}                                   
    for k, v in asdict(d).iteritems():                                          
        if hasattr(v, '__keylist__'):                                           
            out[k] = suds2dict(v)                                               
        elif isinstance(v, list):                                               
            out[k] = []                                                         
            for item in v:                                                      
                if hasattr(item, '__keylist__'):                                
                    out[k].append(suds2dict(item))                              
                else:                                                           
                    out[k].append(item)                                         
        else:                                                                   
            out[k] = v                                                          
    return out                                                                  


def dict2suds(d):                                                               
    """                                                                         
    Suds object deserializer                                                    
    """                                                                         
    out = {}                                                                    
    for k, v in d.iteritems():                                                  
        if isinstance(v, dict):                                                 
            out[k] = dict2suds(v)                                               
        elif isinstance(v, list):                                               
            out[k] = []                                                         
            for item in v:                                                      
                if isinstance(item, dict):                                      
                    out[k].append(dict2suds(item))                              
                else:                                                           
                    out[k].append(item)                                         
        else:                                                                   
            out[k] = v                                                          
    return SudsFactory.object(out.pop('__class__'), out)