thrift list 泛型 python 怎么使用

 我来答
若以下回答无法解决问题,邀请你更新回答
从空去听8
2017-08-09 · TA获得超过7439个赞
知道大有可为答主
回答量:6907
采纳率:93%
帮助的人:5565万
展开全部
总结
1.首先要编写一个*.thrift文件,这个文件里面定义了结构体和方法
举例:
类似于Java中的属性体和接口
2.定义完这个文件之后,确定你要做哪一端,在客户端或者服务器端都要得到此文件,然后运行sudo thrift --gen py *.thrift(有时候文件夹生成不成功,有时候成功,很奇怪还在找原因)
3.此时在当前目录会生成gen-py文件
4.此时不用管这个文件夹,就可以在编写自己的客户端或者服务器端的py文件了,新建一个py文件,见下面例子:
注:此处引用别人的,客户端:

[html] view plain copy
#!/usr/bin/env python

import sys
sys.path.append('./gen-py')

from helloworld import HelloWorld

from thrift import Thrift
from thrift.transport import TSocket
from thrift.transport import TTransport
from thrift.protocol import TBinaryProtocol

try:
transport = TSocket.TSocket('localhost', 9090)
transport = TTransport.TBufferedTransport(transport)
protocol = TBinaryProtocol.TBinaryProtocol(transport)
client = HelloWorld.Client(protocol)
transport.open()

print "client - ping"
print "server - " + client.ping()

print "client - say"
msg = client.say("Hello!")
print "server - " + msg

transport.close()

except Thrift.TException, ex:
print "%s" % (ex.message)
服务器端:

[html] view plain copy
#!/usr/bin/env python

import socket
import sys
sys.path.append('./gen-py')

from helloworld import HelloWorld
from helloworld.ttypes import *

from thrift.transport import TSocket
from thrift.transport import TTransport
from thrift.protocol import TBinaryProtocol
from thrift.server import TServer

class HelloWorldHandler:
def ping(self):
return "pong"

def say(self, msg):
ret = "Received: " + msg
print ret
return ret

handler = HelloWorldHandler()
processor = HelloWorld.Processor(handler)
transport = TSocket.TServerSocket("localhost", 9090)
tfactory = TTransport.TBufferedTransportFactory()
pfactory = TBinaryProtocol.TBinaryProtocolFactory()

server = TServer.TSimpleServer(processor, transport, tfactory, pfactory)

print "Starting thrift server in python..."
server.serve()
print "done!"
1.Thrift有以下几个概念:
类型系统(typesystem)
Thrift定义了一套数据传输描述语言(有点类似IDL),它是“语言中性”的,这个就是它的类型系统。它分为五种类型(数据类型表达3种,预定义类/结构1种,接口表达1种):
基本类型(basictype),也就是bool、byte、i16、i32、i64、double、string,任何语言都有这些基本类型,比较有意思的是string,它即表达text,也表达binary bytes。另一个特点是整型没有unsigned,原因比较简单,因为有些语言不支持。
结构类型(struct):就是C语言中的struct,将基本类型组合起来。
容器类型(container):就是集合类型(list/set/map),其中的元素是任何Thrift可识别的基本、结构、容器类型。【不知道是否有不支持list/set/map的语言,那么Thrift如何处理呢?】
异常类型(exception):从数据结构讲就是结构类型,可以认为是便于异常的处理而单独拿出来的、预定义的、有特殊意义的结构类型。
服务定义类型(service):这个类型实际是用来定义接口的,Thrift代码生成器会根据这个定义,生成代码框架。
传输(transport)
也就是信息的传输渠道以及读写方式,例如,介质可以是socket、shared memory或file,Thrift规定了一些基本的操作(open/close/isOpen/read/write/flush,对server,再加上listen/accept)。特别的,针对Socket方式,有TScoket类,对file方式,有TFileTransport类,上面类比较底层,还有几个实用的类:TBufferedTransport,TFramedTransport,TMemoryBuffer等。

协议(protocol)
是对传输协议的封装,也就是传输采用二进制、XML或者text来表示信息,它的功能有两个:1.双向的消息队列;2.信息的编码和解码(也就是对上面类型的读/写)。关于流式格式,thrift数据类型是自我分割的,意思是说,thrift会自己在数据域的分割处插入标志,在解码的时候,即使没有数据域定义,thrift也能成功分割出各数据域。在若干篇文章中,都提到thrift的二进制流式编码有相当的效率(可以配合压缩),因此首选的协议应该是binary协议。

版本(versioning)
如果一个程序分开来开发,那版本问题就是绕不过去的问题。Thrift的版本是通过“field identifiers”来实现的,每个结构由其标识,结构中的每个域有其标识,这两个标识唯一决定了一个数据域。在解码的时候,数据域的标识被检查,如果不能识别,则该数据域被抛弃。Thrift也可以通过”Isset”机制来明确某些域的设置与否(发送端用来指明是否设置,接收端用来检测是否设置)。
四种情况:
添加了数据域, 旧客户端,新服务器端:客户端发送的数据中没有该域,服务器端能检测出来,可按缺省值处理。
删除了数据域, 旧客户端,新服务器端:客户端发送的数据中有该域,服务器端忽略该域。
添加了数据域, 新客户端,旧服务器端:客户端发送的数据中有该域,服务器端忽略该域。
删除了数据域, 新客户端,旧服务器端:客户端发送的数据中没有该域,服务器端可能不知道如何处理这种情况。
处理器(processor)
就是如何将各部分协调起来,形成代码(或用户代码的框架)。它有两个重要的类:TProcessor和TServer。TProcessor用来实现RPC调用,TServer是所有Server类的基类,TServer类主要处理连接和线程,而不管诸如传输、编码等。用户代码主要关注的一是.thrift文件,二就是这个接口。Thrift为此实现了TSimpleServer(单线程), TThreadedServer(每连接一个线程)和 TThreadPoolServer(线程池)等类。
下图是thrift生成代码的基本结构(C++)。

图中,ServiceIf是根据接口文件(.thrift)生成的虚接口类,用户的具体实现在ServiceHandler中。各种调用方式在TServer中实现。【详细的描述见实例】

2.Thrift实现上的几个考虑
目标语言
虽然有多种选择,但最常用的(可能也是支持最好的)是C++, Java, and Python。

生成的结构体
数据域成员都是公有的,没有set,get之类的东西,虽然建议采用isset,但也可以不用,系统足够强健来处理类似“FieldNotSetException”之类的问题,因而也没有涉及该异常。Read和write方面也是公有的,这样用户可以在固有的RPC之外来使用它们。
RPC方法标识:实现RPC时,建立函数名与函数指针之间的映射,大致如下(不同的语言表达方式不同,C++,map):
std::map<std::string,函数指针> processMap_;
这样加快函数调用。

多线程
对C++实现,在开发过程中,thrift开发人员研究过boost,ACE中与thread,timer相关的东西,开发人员不想引入过多的第三方依赖,因此thrift中只有对boost::shared_ptr的引用是必须的,但为了跨平台或获得更多的功能,一般情况下,boost中thread,timer及其依赖库也是需要的。

ThreadManager和TimerManager
线程管理类用来管理线程池,定时器管理类可以定时触发Runnable的对象,开启一件事情(可以放到或不放到一个单独线程)。

NonblockingOperation
这个东西需要libevent的支持。

Compiler(代码生成器)
这个东西是用C++写的,依赖于lex/yacc。代码生成分两步:第一,检查包含的文件和类型定义文件,生成“解析树”(the parse tree);第二,将各类型放到解析树中,根据解析树生成代码。

TFileTransport
这个类(及其继承类)可以将request消息记入文件,为提高性能,它先缓存记录,并存入磁盘。记录文件是分块的(文件固定大小),采用padding,记录不能跨块。
本回答被提问者采纳
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
收起 1条折叠回答
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式