使用tornado,我们可以做什么?

王朝学院·作者佚名  2016-08-27
窄屏简体版  字體: 小  |  中  |  大  |  超大  

以下介绍都是建立在python2.x的基础上面,tornado使用任意版本皆可。

如果我们需要对外提供一个http server(web api)/websocket server时,我们都可以使用tornado,以下是一个基于tornado的rest的应用简介。

当我们下载好了tornado以后,可以按照tornado的文档demo,复制一份监听代码过来,代码如下:

importtornado.ioloopimporttornado.webclassMainHandler(tornado.web.RequestHandler):defget(self):

self.write("Hello, world")application=tornado.web.Application([

(r"/", MainHandler),

])if__name__=="__main__":

application.listen(8888)

tornado.ioloop.IOLoop.instance().start()

View Code

这一段代码在运行时就已经可以开始监听并返回信息了,然后开始按照rest的规范开始改写,我们首先需要对url的path进行定位,根据path执行相对应的代码,则有了以下代码:

importos.pathimporttornado.escapeimporttornado.ioloopimporttornado.optionsimporttornado.webimporttornado.websocketimporttornado.httpserverimporttoolsimportapplogicfromconfigimportconfigclassApplication(tornado.web.Application):def__init__(self):

handlers=[

(r"/.*?", WebHandler),

]

settings=dict(

cookie_secret="__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__",

template_path=os.path.join(os.path.dirname(__file__),"templates"),

static_path=os.path.join(os.path.dirname(__file__),"static"),

xsrf_cookies=False

)

tornado.web.Application.__init__(self, handlers, **settings)classWebHandler(tornado.web.RequestHandler):defget(self):

path=self.request.path

command= path[path.rfind('/') +1:]

result=applogic.execute(self, command, self.get_argument)ifresult:

to_message=tools.dumps(result)

self.write(to_message)defpost(self):

path=self.request.path

command= path[path.rfind('/') +1:]

obj=tools.loads(self.request.body)

result=applogic.execute(self, command, obj)ifresult:

to_message=tools.dumps(result)

self.write(to_message)defmain():

app=Application()

http_server=tornado.httpserver.HTTPServer(app)

http_server.bind(config.default['main_port'], config.default['host'])

tornado.ioloop.IOLoop.instance().start()

View Code

我们对path做了最后一级目录的截取,由于客观原因,多级目录的则需要看客们自行实现。

applogic是我们的具体的逻辑代码门面类,因为是脚本语言的关系,所以这里使用一个相对巧妙的ioc,代码如下:

defexecute(handler, command, obj):ifmain_map.has_key(command):

result=main_map[command](handler, obj)ifresult:

response.send(handler, result)else:

handler.send_error(404)defcreate(handler, obj):

flag=papercache.push(obj)

result={}ifflag:

result={'code':0

}else:

result={'code':1,'errorMsg':'param is error'}returnresultdefgrab(handler, obj):

id= obj.has_key('id')andobj['id']orNone

result={'code':1,'errorMsg':'redpaper is empty','money':0

}ifid:

money=papercache.pop_queue(id)ifmoney:

result={'money': money,'code': 0

}returnresult

main_map={'create':create,'grab':grab

}

View Code

我们将具体的执行逻辑,放在定义好的function里面,然后将function的引用放在一个字典里面,然后根据command(最后一级目录对应的字符串),来执行具体的代码。

我们将返回的数据做了一个封装,因为实际应用里面的数据格式,可能采用的是json,或者是其它自定义的协议,所以我们有一个response的封装,代码如下:

defsend(handler, obj):iftype(handler)isnotNone:

obj=tools.dumps(obj)

handler.write(obj)

View Code

tools的代码如下:

importjsondefdumps(obj):

obj=toUnicode(obj)ifobj:

obj=json.dumps(obj)

obj=str(obj)returnobjdefloads(obj):ifobj:

obj=json.loads(str(obj))

obj=toUtf8(obj)returnobj

View Code

因为可能存在中文的关系,所以加了一个Utf8的转换,,基于websocket的也是同理,则在监听的时候,使用WebSocketHandle,代码如下:

importos.pathimporttornado.escapeimporttornado.ioloopimporttornado.optionsimporttornado.webimporttornado.websocketimporttornado.httpserverimporttoolsimportapplogicfromconfigimportconfigclassApplication(tornado.web.Application):def__init__(self):

handlers=[

(r"/web", MainHandler)

(r"/.*?", WebHandler),

]

settings=dict(

cookie_secret="__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__",

template_path=os.path.join(os.path.dirname(__file__),"templates"),

static_path=os.path.join(os.path.dirname(__file__),"static"),

xsrf_cookies=False

)

tornado.web.Application.__init__(self, handlers, **settings)classMainHandler(tornado.websocket.WebSocketHandler):defallow_draft76(self):returnTruedefopen(self):

token= self.get_cookie('token')ifnottoken:PRint"long not token"self.close()else:print('connect')defon_close(self):print('close');defon_message(self, message):

obj=tools.loads(message)

command= obj.has_key('command')andobj['command']orNone

body= obj.has_key('body')andobj['body']orNone

result=applogic.execute(self, command, body)ifresult:

to_message=tools.dumps(result)

self.write(to_message)returnclassWebHandler(tornado.web.RequestHandler):defget(self):

path=self.request.path

command= path[path.rfind('/') +1:]

result=applogic.execute(self, command, self.get_argument)ifresult:

to_message=tools.dumps(result)

self.write(to_message)defpost(self):

path=self.request.path

command= path[path.rfind('/') +1:]

obj=tools.loads(self.request.body)

result=applogic.execute(self, command, obj)ifresult:

to_message=tools.dumps(result)

self.write(to_message)defmain():

app=Application()

http_server=tornado.httpserver.HTTPServer(app)

http_server.bind(config.default['main_port'], config.default['host'])

tornado.ioloop.IOLoop.instance().start()

View Code

可能你们会觉得怎么多了个command和body出来了,因为我的通讯协议是假定{"command":"", "body":""},这样的json格式。

那一个简易的基于python的rest服务和websocket通讯服务器到这里就结束了

 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
© 2005- 王朝網路 版權所有 導航