在Python中序列化suds对象

20 投票
7 回答
16895 浏览
提问于 2025-04-15 20:13

好的,我正在努力提高我的Python水平,所以我不太确定我现在的做法是否正确,但这是我目前遇到的问题……

我需要通过SOAP方法获取一些信息,现在只用到部分信息,但我想把整个结果存起来,以便将来使用(我们希望尽量少调用这个服务)。在查找访问这个服务的最佳方法时,我发现suds是个不错的选择,它简单易用,能顺利获取数据。但是现在我想以某种方式保存这个结果,最好是序列化后存到数据库里,这样我以后可以再提取出来,继续使用。

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

更新

阅读了如何序列化suds结果?的最佳答案后,我对为什么这不是一个选项有了更好的理解,我想我可能得重新创建一个包含我需要的信息的基本对象?

7 个回答

6

这是我在研究之前想到的一个方法。这个方法在处理复杂的suds响应时效果很好,也适用于其他对象,比如__builtins__,因为这个解决方案不依赖于suds。

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

这个方法有效,而且实际上更快。它也适用于那些没有__keylist__属性的对象。

我对一个复杂的suds输出对象进行了100次性能测试,这个方法的运行时间在0.04到0.052秒之间(平均0.045724287秒)。而上面提到的recursive_asdict方法的运行时间在0.082到0.102秒之间,几乎是前者的两倍(平均0.0829765582秒)。

然后我又回去重新设计了这个函数,以提高性能,并且不需要导入datetime。我利用了__keylist__属性,所以这个方法不适用于其他对象,比如__builtins__,但在处理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.018到0.033秒之间(平均0.0260889721秒),所以比recursive_asdict方法快了将近4倍。

35

我一直在用以下方法把Suds对象转换成JSON格式:

from suds.sudsobject import asdict

def recursive_asdict(d):
    """Convert Suds object into serializable format."""
    out = {}
    for k, v in asdict(d).items():
        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))
7

是的,我确认我在你提到的回答中给出的解释——动态生成的类不容易被保存成文件(或者说不容易被序列化),你需要提取出所有的状态信息,把这些状态保存下来,然后在取出来的时候再重建那个复杂的对象,如果你真的想用的话;-)。

撰写回答