• Python Thrift 简单示例


    本文基于Thrift-0.10,使用Python实现服务器端,使用Java实现客户端,演示了Thrift RPC调用示例。Java客户端提供两个字符串参数,Python服务器端计算这两个字符串的相似度,并返回相似度结果(double类型,范围[0, 1],0表示不相似,1表示完全相同)

    一,环境安装

    开发环境:Windows10,PyCharm2016,Anaconda3,Python3.6

    首先安装python 的thrift包:windows打开Anaconda prompt,输入:conda install -c anaconda thrift   安装thrift包。

    输入:conda list 可查看系统中已经安装了哪些包,及包的版本,如下图所示:我们安装的是:thrift-0.10.0

    在写代码之前,需要先定义一个 .thrift文件,然后使用Thrift Compiler生成相应的Thrift服务需要依赖的“文件”

    ①定义.thrift文件

    namespace py similarityservice
    namespace java similarityservice
    
    service ChatSimilarityService{
        double similarity(1:string chat1, 2:string chat2),
    }

    namespace提供了一种组织代码的方式。其实就是,生成的文件放在:similarityservice这个文件夹下。

    由于前面的Python安装的thrift-0.10,因此在官网上下载:thrift-0.10.exe,将它放在与 .thrift相同的目录下,cmd切换到该目录下,执行命令:

    .	hrift-0.10.0.exe --gen py chat_similarity.thrift

    生成的文件如下,将它们放在合适的python包下,即可供python 服务端程序 import 了。

    二,Python服务端实现

    pycharm thrift插件支持

    可以去pycharm插件官网下载一个thrift插件,安装好之后,编写 .thrift 文件能够自动补全提示。

    服务端的实现 主要有以下五方面:(个人理解,可能有错)

    ①Handler

    服务端业务处理逻辑。这里就是业务代码,比如 计算两个字符串 相似度

    ②Processor

    从Thrift框架 转移到 业务处理逻辑。因此是RPC调用,客户端要把 参数发送给服务端,而这一切由Thrift封装起来了,由Processor将收到的“数据”转交给业务逻辑去处理

    ③Protocol

    数据的序列化与反序列化。客户端提供的是“字符串”,而数据传输是一个个的字节,因此会用到序列化与反序列化。

    ④Transport

    传输层的数据传输。

    ⑤TServer

    服务端的类型。服务器以何种方式来处理客户端请求,比如,一次Client请求创建一个新线程呢?还是使用线程池?……可参考:阻塞通信之Socket编程

    TSimpleServer —— 单线程服务器端使用标准的阻塞式 I/O

    TThreadPoolServer —— 多线程服务器端使用标准的阻塞式 I/O

    TNonblockingServer —— 多线程服务器端使用非阻塞式 I/O

    把上面生成的thrift文件复制到 thrift_service包下,如下图:

    整个python 服务端的完整代码如下:

    复制代码
     1 from thrift.protocol import TBinaryProtocol
     2 from thrift.server import TServer
     3 from thrift.transport import TSocket, TTransport
     4 
     5 from text.thrift_service.similarityservice import ChatSimilarityService
     6 
     7 from difflib import SequenceMatcher
     8 from pypinyin import pinyin
     9 import zhon
    10 import pypinyin
    11 from zhon.hanzi import punctuation
    12 import re
    13 
    14 __HOST = '127.0.0.1'
    15 __PORT = 9090
    16 
    17 
    18 def similar_num(list1, list2):
    19     return len(set(list1).intersection(list2))
    20 
    21 
    22 def similar_ration(str1, str2):
    23     return SequenceMatcher(lambda x: x == ' ', str1, str2).ratio()
    24 
    25 class SimilarityHandler(ChatSimilarityService.Iface):
    26     def __init__(self):
    27         self.log={}
    28     def ping(selfs):
    29         print('ping')
    30 
    31     def similarity(self, chat1, chat2):
    32         #去掉中文字符串中的特殊标点符号
    33         list1 = re.findall('[^{}]'.format(zhon.hanzi.punctuation), chat1)
    34         list2 = re.findall('[^{}]'.format(zhon.hanzi.punctuation), chat2)
    35 
    36         #将标点符号转换成拼音
    37         pinyin1 = pinyin(list1, style=pypinyin.STYLE_NORMAL)
    38         pinyin2 = pinyin(list2, style=pypinyin.STYLE_NORMAL)
    39 
    40         #将所有的拼音统一保存到 单个list 中
    41         pinyin_list1 = [word[0] for word in pinyin1]
    42         pinyin_list2 = [word[0] for word in pinyin2]
    43 
    44         #计算 list 中元素相同的个数
    45         result1 = similar_num(pinyin_list1, pinyin_list2)
    46 
    47         #list convert to string
    48         str1_pinyin = ''.join(pinyin_list1)
    49         str2_pinyin = ''.join(pinyin_list2)
    50         #计算字符串的相似度
    51         result2 = similar_ration(str1_pinyin, str2_pinyin)
    52 
    53         print('ratio:{}, nums:{}'.format(result2, result1))
    54         return result2
    55 
    56 
    57 if __name__ == '__main__':
    58     handler = SimilarityHandler()
    59     processor = ChatSimilarityService.Processor(handler)
    60     transport = TSocket.TServerSocket(host=__HOST, port=__PORT)
    61     tfactory = TTransport.TBufferedTransportFactory()
    62     pfactory = TBinaryProtocol.TBinaryProtocolFactory()
    63 
    64     server = TServer.TThreadPoolServer(processor, transport, tfactory, pfactory)
    65 
    66     print('Starting the server')
    67     server.serve()
    68     print('done')
    复制代码

    这里简单地介绍下实现思路:

    ①使用python 的 zhon 包过滤掉中文中出现的标点符号等特殊字符

    ②python的 pypinyin 包 将中文转换成字符串(其实也可以直接比较中文字符串的相似度,但我这里转换成了拼音,就相当于比较英文字符串了)

    ③使用python 的 difflib 包中的SequenceMatcher 类来计算两个字符串之间的相似度

    三,Java客户端实现

    ①在maven工程的pom.xml中添加thrift依赖。这里的libthrift版本、windows10下载的thrift compiler版本(thrift-0.10.0.exe),还有 python的 thrift包的版本 最好保持一致。

            <!-- https://mvnrepository.com/artifact/org.apache.thrift/libthrift -->
            <dependency>
                <groupId>org.apache.thrift</groupId>
                <artifactId>libthrift</artifactId>
                <version>0.10.0</version>
            </dependency>

    ②cmd命令行执行:. hrift-0.10.0.exe --gen java chat_similarity.thrift  生成 ChatSimilarityService.java 文件,Java 客户端代码需要依赖它。

    整个Java Client的代码如下:

    复制代码
     1 import thrift.similarityservice.ChatSimilarityService;
     2 import org.apache.thrift.TException;
     3 import org.apache.thrift.protocol.TBinaryProtocol;
     4 import org.apache.thrift.protocol.TProtocol;
     5 import org.apache.thrift.transport.TSocket;
     6 import org.apache.thrift.transport.TTransport;
     7 
     8 /**
     9  * Created by Administrator on 2017/12/20.
    10  */
    11 public class SimilarityThriftClient {
    12 
    13     public static void main(String[] args) {
    14         try {
    15             TTransport transport;
    16             transport = new TSocket("127.0.0.1", 9090);
    17             transport.open();
    18 
    19             TProtocol protocol = new TBinaryProtocol(transport);
    20             ChatSimilarityService.Client client = new ChatSimilarityService.Client(protocol);
    21             perform(client);
    22             transport.close();
    23 
    24         } catch (TException e) {
    25             e.printStackTrace();
    26         }
    27     }
    28     private static void perform(ChatSimilarityService.Client client)throws TException {
    29         String chat1 = "您好。";
    30         String chat2 = "你好";
    31         double ratio = client.similarity(chat1, chat2);
    32         System.out.println(ratio);
    33     }
    34 }
    复制代码

    四,总结

    本文介绍了一个简单的 Python Server、Java Client的Thrift服务调用示例。关于Thrift可参考:

    Thrift Tutorial

    Apache Thrift - 可伸缩的跨语言服务开发框架

    Thrift 安装及使用

  • 相关阅读:
    软件开发规范
    Fail2ban + firewalld 防护doss攻击
    SourceTree&Git部分名词解释
    训子
    一个网络下,手机如何访问本地网址
    tempalte.js的一般用法
    template.js的介绍
    获取URL中的参数
    js判断苹果和安卓端或者wp端
    HTML5与WebGL编程
  • 原文地址:https://www.cnblogs.com/ExMan/p/10408401.html
Copyright © 2020-2023  润新知