在Python中序列化suds对象
好的,我正在努力提高我的Python水平,所以我不太确定我现在的做法是否正确,但这是我目前遇到的问题……
我需要通过SOAP方法获取一些信息,现在只用到部分信息,但我想把整个结果存起来,以便将来使用(我们希望尽量少调用这个服务)。在查找访问这个服务的最佳方法时,我发现suds是个不错的选择,它简单易用,能顺利获取数据。但是现在我想以某种方式保存这个结果,最好是序列化后存到数据库里,这样我以后可以再提取出来,继续使用。
那么,最好的方法是什么呢?看起来pickle/json不是一个选项?谢谢!
更新
阅读了如何序列化suds结果?的最佳答案后,我对为什么这不是一个选项有了更好的理解,我想我可能得重新创建一个包含我需要的信息的基本对象?
7 个回答
这是我在研究之前想到的一个方法。这个方法在处理复杂的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倍。
我一直在用以下方法把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))
是的,我确认我在你提到的回答中给出的解释——动态生成的类不容易被保存成文件(或者说不容易被序列化),你需要提取出所有的状态信息,把这些状态保存下来,然后在取出来的时候再重建那个复杂的对象,如果你真的想用的话;-)。