IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

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

    双调发表于 2015-11-02 12:21:00
    love 0

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

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

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

    import tornado.ioloop
    import tornado.web

    class MainHandler(tornado.web.RequestHandler):
    def get(self):
    self.write(
    "Hello, world")

    application
    = tornado.web.Application([
    (r
    "/", MainHandler),
    ])

    if __name__ == "__main__":
    application.listen(
    8888)
    tornado.ioloop.IOLoop.instance().start()

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

    import os.path
    import tornado.escape
    import tornado.ioloop
    import tornado.options
    import tornado.web
    import tornado.websocket
    import tornado.httpserver
    import tools
    import applogic
    from config import config

    class Application(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)

    class WebHandler(tornado.web.RequestHandler):
    def get(self):
    path
    = self.request.path
    command
    = path[path.rfind('/') +1:]
    result
    = applogic.execute(self, command, self.get_argument)
    if result:
    to_message
    = tools.dumps(result)
    self.write(to_message)


    def post(self):
    path
    = self.request.path
    command
    = path[path.rfind('/') +1:]
    obj
    = tools.loads(self.request.body)
    result
    = applogic.execute(self, command, obj)
    if result:
    to_message
    = tools.dumps(result)
    self.write(to_message)

    def main():
    app
    = Application()
    http_server
    = tornado.httpserver.HTTPServer(app)
    http_server.bind(config.default[
    'main_port'], config.default['host'])
    tornado.ioloop.IOLoop.instance().start()

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

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

    def execute(handler, command, obj):
    if main_map.has_key(command):
    result
    = main_map[command](handler, obj)
    if result:
    response.send(handler, result)
    else:
    handler.send_error(
    404)


    def create(handler, obj):
    flag
    = papercache.push(obj)
    result
    = {}
    if flag:
    result
    = {
    'code':0
    }
    else:
    result
    = {
    'code':1,
    'errorMsg':'param is error'
    }
    return result

    def grab(handler, obj):
    id
    = obj.has_key('id') and obj['id'] or None
    result
    = {
    'code':1,
    'errorMsg':'redpaper is empty',
    'money':0
    }
    if id:
    money
    = papercache.pop_queue(id)
    if money:
    result
    = {
    'money' : money,
    'code': 0
    }
    return result


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

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

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

    def send(handler, obj):
    if type(handler) is not None:
    obj
    = tools.dumps(obj)
    handler.write(obj)

    tools的代码如下:

    import json


    def dumps(obj):
    obj
    = toUnicode(obj)
    if obj:
    obj
    = json.dumps(obj)
    obj
    = str(obj)
    return obj

    def loads(obj):
    if obj:
    obj
    = json.loads(str(obj))
    obj
    = toUtf8(obj)
    return obj

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

    import os.path
    import tornado.escape
    import tornado.ioloop
    import tornado.options
    import tornado.web
    import tornado.websocket
    import tornado.httpserver
    import tools
    import applogic
    from config import config

    class Application(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)

    class MainHandler(tornado.websocket.WebSocketHandler):
    def allow_draft76(self):
    return True

    def open(self):
    token
    = self.get_cookie('token')
    if not token:
    print "long not token"
    self.close()
    else:
    print('connect')

    def on_close(self):
    print('close');

    def on_message(self, message):
    obj
    = tools.loads(message)
    command
    = obj.has_key('command') and obj['command'] or None
    body
    = obj.has_key('body') and obj['body'] or None
    result
    = applogic.execute(self, command, body)
    if result:
    to_message
    = tools.dumps(result)
    self.write(to_message)
    return

    class WebHandler(tornado.web.RequestHandler):
    def get(self):
    path
    = self.request.path
    command
    = path[path.rfind('/') +1:]
    result
    = applogic.execute(self, command, self.get_argument)
    if result:
    to_message
    = tools.dumps(result)
    self.write(to_message)


    def post(self):
    path
    = self.request.path
    command
    = path[path.rfind('/') +1:]
    obj
    = tools.loads(self.request.body)
    result
    = applogic.execute(self, command, obj)
    if result:
    to_message
    = tools.dumps(result)
    self.write(to_message)

    def main():
    app
    = Application()
    http_server
    = tornado.httpserver.HTTPServer(app)
    http_server.bind(config.default[
    'main_port'], config.default['host'])
    tornado.ioloop.IOLoop.instance().start()

     

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

     

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

     


    本文链接:使用tornado,我们可以做什么?,转载请注明。



沪ICP备19023445号-2号
友情链接