Python MessagePack和datetime

Python MessagePack和datetime,python,datetime,python-3.x,zeromq,msgpack,Python,Datetime,Python 3.x,Zeromq,Msgpack,我需要一种在python多处理进程之间每秒通过zeromq发送300条短消息的快速方法。每条消息都需要包含一个ID和时间() msgpack似乎是在通过zeromq发送dict之前序列化dict的最佳方式,而且方便的是,msgpack有一个我需要的示例,只是它有一个datetime.datetime.now() 问题是他们的示例不起作用,我得到以下错误: obj = datetime.datetime.strptime(obj["as_str"], "%Y%m%dT%H:%M:%S.%f

我需要一种在python多处理进程之间每秒通过
zeromq
发送300条短消息的快速方法。每条消息都需要包含一个
ID
时间()

msgpack
似乎是在通过
zeromq
发送dict之前序列化dict的最佳方式,而且方便的是,
msgpack
有一个我需要的示例,只是它有一个
datetime.datetime.now()

问题是他们的示例不起作用,我得到以下错误:

    obj = datetime.datetime.strptime(obj["as_str"], "%Y%m%dT%H:%M:%S.%f")
KeyError: 'as_str'

可能是因为我使用的是Python3.4,但我不知道strTime有什么问题。非常感谢您的帮助。

Python3和Python2管理不同的字符串编码:

然后需要:

  • 使用
    b'as_str'
    (而不是
    'as_str'
    )作为字典键
  • 对存储值使用
    encode
    decode
这样修改代码适用于python2和python3:

import datetime
import msgpack

useful_dict = {
    "id": 1,
    "created": datetime.datetime.now(),
}

def decode_datetime(obj):
    if b'__datetime__' in obj:
        obj = datetime.datetime.strptime(obj[b'as_str'].decode(), "%Y%m%dT%H:%M:%S.%f")
    return obj

def encode_datetime(obj):
    if isinstance(obj, datetime.datetime):
        obj = {'__datetime__': True, 'as_str': obj.strftime("%Y%m%dT%H:%M:%S.%f").encode()}
    return obj


packed_dict = msgpack.packb(useful_dict, default=encode_datetime)
this_dict_again = msgpack.unpackb(packed_dict, object_hook=decode_datetime)
鉴于messagepack(
import msgpack
)擅长序列化整数,我创建了一个只使用整数的解决方案:

\u datetime\u ExtType=42
def_解包器_挂钩(代码、数据):
如果代码==\u日期时间\u外部类型:
值=解包(数据)
如果len(values)=8:#我们有时区
返回datetime.datetime(*值[:-1],dateutil.tz.tzoffset(无,值[-1]))
其他:
返回datetime.datetime(*值)
返回msgpack.ExtType(代码、数据)
#这只会被未知类型调用
def包装机未知处理程序(obj):
如果isinstance(对象,datetime.datetime):
如果obj.tzinfo:
组件=(obj.year、obj.month、obj.day、obj.hour、obj.minute、obj.second、obj.microsecond、int(obj.utcoffset().total_seconds())
其他:
组件=(对象年、对象月、对象日、对象小时、对象分钟、对象秒、对象微秒)
#我们有效地将值加倍打包以“压缩”它们
data=msgpack.ExtType(_datetime_ExtType,pack(components))
返回数据
raise TypeError(“未知类型:{}”.format(obj))
def包(obj,**kwargs):
#我们不使用全球包装机,因为它不会对重新进入者安全
返回msgpack.packb(obj,use\u bin\u type=True,default=\u packer\u unknown\u handler,**kwargs)
def解包(有效负载):
尝试:
#我们在解包期间临时禁用gc以提高性能:https://pypi.python.org/pypi/msgpack-python
gc.disable()
#这必须与上述封隔器参数相匹配。注意:使用列表更快
返回msgpack.unpackb(有效负载,使用列表=False,编码=utf-8',ext\u hook=\u unpacker\u hook)
最后:
gc.enable()
中,它指出
packb
(和
pack
)的unicode字符串的默认编码是utf-8。您只需在
decode\u datetime
函数中搜索unicode字符串
“\uu datetime”
,而不是字节对象
b'\uu datetime
,然后将
编码='utf-8'
参数添加到
解包
。像这样:

def decode_datetime(obj):
    if '__datetime__' in obj:
        obj = datetime.datetime.strptime(obj["as_str"], "%Y%m%dT%H:%M:%S.%f")
    return obj

packed_dict = msgpack.packb(useful_dict, default=encode_datetime)
this_dict_again = msgpack.unpackb(packed_dict, object_hook=decode_datetime, encoding='utf-8')

顺便说一句,我后来意识到这个特殊的解决方案很好地维护了原始时区。但是更好的解决方案是如果我们有时区,使用utc时间戳,否则就进行日期序列化。
def decode_datetime(obj):
    if '__datetime__' in obj:
        obj = datetime.datetime.strptime(obj["as_str"], "%Y%m%dT%H:%M:%S.%f")
    return obj

packed_dict = msgpack.packb(useful_dict, default=encode_datetime)
this_dict_again = msgpack.unpackb(packed_dict, object_hook=decode_datetime, encoding='utf-8')