使用格式模式将字符串反序列化为值

时间:2014-03-05 14:02:02

标签: python serialization format

我正在努力为(解)序列化器找到一个好的解决方案。 我有一个格式模式和所有值。

格式模式如下:

msg = '$bla,%d,%02d,%02d %02d:%02d:%02d.%03d' % (kwargs['...'], ...)

当我序列化值时,我得到以下字符串:

bla,1990,12,24 13:37:11.001

但我也必须反序列化它。图案的长度和类型可能有很大差异。 我想仅根据格式模式对字符串进行反序列化。

任何想法如何实现这一目标?

编辑:我正在使用Python 2.7.6

2 个答案:

答案 0 :(得分:2)

如果你可以完全控制协议,或者说format after serialization,我建议使用一些现有的解决方案,例如Python标准库提供的PickleJson在网络上非常流行,或Protobuf这是Google提供的跨语言

Pickle

>>> 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())