Thrift Python版本中文传输问题和解决

前段时间项目内用到了Thrift封装C/S交换数据,这东西好处自然是每个平台都有相应的框架实现,客户端不用关心具体逻辑,有了.thrift定义后直接调接口(作为软饭,个人觉得用起来没有WCF舒服,这么好的东西微软不下力气推广啊)。

Java和C++写的Server都顺利调试通过,卡在Python的一个实现出现的问题上了。好吧,先不要问为什么一定要用Python做Server,这涉及到项目内的一些糟事,略过。具体问题表现是:自己定义的object,两个string field只有一个可以成功赋值。如果给其中一个赋值后,另外一个一定是空字符串。

尝试过各种情况,发现中文出现的时候复现。在Python中提到中文问题,那么自然先想到str、unicode这两个类型在搞鬼。算幸运的是,在盲目调试了一天之后,找到了好用的解决方案。文中的解决方法好用,但需要修改thrift本身代码。对于部署在实际服务器上的服务来说,可能不太适用,所以可以这样做:

class MyTBinaryProtocol(TBinaryProtocol.TBinaryProtocol):
    def __init__(self, trans, strictRead=False, strictWrite=True):
        TBinaryProtocol.TBinaryProtocol.__init__(self, trans, strictRead, strictWrite)

    def writeString(self, str):
        if type(str) is unicode:
            str = str.encode('utf-8')
        self.writeI32(len(str))
        self.trans.write(str)

class MyTBinaryProtocolFactory(TBinaryProtocol.TBinaryProtocolFactory):
    def __init__(self, strictRead=False, strictWrite=True):
        TBinaryProtocol.TBinaryProtocolFactory.__init__(self, strictRead, strictWrite)

    def getProtocol(self, trans):
        prot = MyTBinaryProtocol(trans, self.strictRead, self.strictWrite)
        return prot

然后启动Server的部分修改为:

pfactory = MyTBinaryProtocolFactory()