我正在努力为(解)序列化器找到一个好的解决方案。 我有一个格式模式和所有值。
格式模式如下:
msg = '$bla,%d,%02d,%02d %02d:%02d:%02d.%03d' % (kwargs['...'], ...)
当我序列化值时,我得到以下字符串:
bla,1990,12,24 13:37:11.001
但我也必须反序列化它。图案的长度和类型可能有很大差异。 我想仅根据格式模式对字符串进行反序列化。
任何想法如何实现这一目标?
编辑:我正在使用Python 2.7.6
答案 0 :(得分:2)
如果你可以完全控制协议,或者说format after serialization
,我建议使用一些现有的解决方案,例如Python标准库提供的Pickle,Json在网络上非常流行,或Protobuf这是Google提供的跨语言
>>> import pickle
>>> formattuple = (1990,12,24,13,37,11,1)
>>> s = pickle.dumps(formattuple)
>>> s
'(I1990\nI12\nI24\nI13\nI37\nI11\nI1\ntp0\n.'
>>> pickle.loads(s)
(1990, 12, 24, 13, 37, 11, 1)
Json:
>>> import json
>>> formattuple = (1990,12,24,13,37,11,1)
>>> s = json.dumps(formattuple)
>>> s
'[1990, 12, 24, 13, 37, 11, 1]'
>>> json.loads(s)
[1990, 12, 24, 13, 37, 11, 1]
请注意json有一些限制,比如序列化和反序列化除dict,list和tuple之外的对象有点困难。并且不会反序列化为完全相同的格式,因为某些数据结构(如元组)在json中不存在
Protobuf是一个功能更强大但更复杂的解决方案。您需要首先定义数据模式。
答案 1 :(得分:1)
您可以使用正则表达式执行此操作,并进行一些假设。这是一个部分示例,您可能需要添加一个完整的解决方案。基本上,我们将每种打印格式转换为与其匹配的正则表达式。
import re
formattuple = (1990,12,24,13,37,11,1)
formatstr = 'bla,%d,%02d,%02d %02d:%02d:%02d.%03d'
def rep_format(fmt):
fmt = fmt.group(0)
if fmt[0] != '%':
return fmt
if fmt == '%d':
return r'(\d+)'
ftype = fmt[-1]
if ftype == 'd':
fwidth = int(fmt[1:-1])
return r'(\d{%d})'%(fwidth)
else:
return fmt
scanstr = re.sub(r'%\d+[df]', rep_format, formatstr)
scanstr
'bla,(\\d+),(\\d{2}),(\\d{2}) (\\d{2}):(\\d{2}):(\\d{2}).(\\d{3})'
fstr = formatstr%formattuple
fstr
'bla,1990,12,24 13:37:11.001'
match = re.match(scanstr, fstr)
match.groups()
('1990',
'12',
'24',
'13',
'37',
'11',
'001')
mtuple = tuple(int(x) for x in match.groups())