简介
Tornado是一个Python web框架和异步网络库,利用非阻塞网络IO,文档中声明可支持千万级连接,处理长连接,WebSockets的理想选择。
使用Tornado搭建Web服务也非常简单和方便,接下来我们实现一个Web服务搭建。
Web服务搭建
基于Tornado搭建Web服务,前提先安装tornado,下载链接 https://pypi.python.org/pypi/tornado,也可以直接利用pip install tornado
完成安装。
主要依赖tornado的部分是:
- tornado.web.Application: 构建Application,声明接口url和handler
- tornado.web.RequestHandler:构建handler,获取request中的参数,实现具体操作。
- tornado.escape.json_encode:构造json,用于结果输出
为实现Web服务的搭建,我们以时间戳和时间字符串的转换为例,实现了如下几个部件:
- 处理输出的JsonUtils
- 时间处理TimeUtils
- 入口Application
- 时间处理TimeHandler
- 时间戳处理TimestampHandler
JsonUtils
处理输出结果,转换为JSON,正常处理状态码为0,否则为-1。代码如下:
class JsonUtils(object):
@staticmethod
def success(response, cost_time):
"""
正确返回
:param response: 返回结果
:param cost_time: 耗时
:return: string, {"status_msg": "ok", "status_code": 0, "cost_time":, "response": }
"""
return json_encode({"status_msg": "ok", "status_code": 0, "cost_time": cost_time, "response": response})
@staticmethod
def error(message, cost_time):
"""
错误返回
:param message: 错误信息
:param cost_time: 耗时
:return: string,
"""
return json_encode({"status_msg": str(message), "status_code": -1, "cost_time": cost_time, "response": None})
TimeUtils
时间处理工具,将字符串转换为时间戳,将时间戳转换为时间字符串,主要被Handler调用,代码如下:
class TimeUtils(object):
"""
时间处理方法
"""
def __init__(self):
self.time_format = "%Y-%m-%d %H:%M:%S"
def time2timestamp(self, time_str):
"""
时间转换为时间戳
:param time_str: 时间字符串,不进行格式校验
:return: 时间戳
"""
return time.mktime(time.strptime(time_str, self.time_format))
def timestamp2time(self, timestamp):
"""
时间戳转换为时间字符串
:param timestamp: 时间戳
:return: 时间字符串
"""
return time.strftime(self.time_format, time.localtime(timestamp))
TimeHandler
将时间字符串转换为时间戳处理,实现了get方法,接收time字段,调用TimeUtils的方法,实现时间转换。
class TimeHandler(tornado.web.RequestHandler):
def data_received(self, chunk):
pass
def initialize(self, handler):
self.handler = handler
def get(self):
"""
get方法实现
处理正常返回:转换之后的时间戳
处理异常返回:错误信息
"""
result = None
start_time = time.time()
time_str = self.get_argument("time", default="")
if not time_str:
msg = "missing parameter 'time' "
result = JsonUtils.error(msg, time.time() - start_time)
else:
flag, timestamp = self._process(time_str)
if not flag:
result = JsonUtils.error(timestamp, time.time() - start_time)
else:
result = JsonUtils.success({"timestamp": timestamp}, time.time() - start_time)
self.write(result)
def _process(self, time_str):
"""
时间转换方法
:param time_str: 时间字符串
:return: True, 时间戳
"""
try:
return True, self.handler.time2timestamp(time_str)
except Exception as e:
return False, str(e)
TimestampHandler
将时间戳转换为时间字符串处理,实现了get方法,接收timestamp字段,调用TimeUtils的方法,实现时间戳转换。
class TimestampHandler(tornado.web.RequestHandler):
def data_received(self, chunk):
pass
def initialize(self, handler):
self.handler = handler
def get(self):
"""
get方法实现
处理正常返回:转换之后的时间字符串
处理异常返回:错误信息
"""
result = None
start_time = time.time()
timestamp = self.get_argument("timestamp", default="")
if not timestamp:
msg = "missing parameter 'timestamp' "
result = JsonUtils.error(msg, time.time() - start_time)
else:
flag, time_str = self._process(timestamp)
if not flag:
result = JsonUtils.error(time_str, time.time() - start_time)
else:
result = JsonUtils.success({"time": time_str}, time.time() - start_time)
self.write(result)
def _process(self, timestamp):
"""
时间转换方法
:param timestamp: 时间戳
:return: True, 时间字符串
"""
try:
return True, self.handler.timestamp2time(float(timestamp))
except Exception as e:
return False, str(e)
Application
入口Application,利用TimeHandler和TimestampHandler构建时间转换2个handler,处理请求。
class WebServerApplication(object):
def __init__(self, port, time_handler):
self.port = port
self.time_handler = time_handler
def make_app(self):
"""
构建Handler,
(): 一个括号内为一个Handler
"""
return tornado.web.Application([
(r"/time?", TimeHandler, dict(handler=self.time_handler)),
(r"/timestamp?", TimestampHandler, dict(handler=self.time_handler))], )
def process(self):
"""
构建app, 监听post, 启动服务
"""
app = self.make_app()
app.listen(self.port)
tornado.ioloop.IOLoop.current().start()
组件组合
将构造的组件组合在一起,启动服务。
#!/usr/bin/python
# -*-coding=utf-8 -*-
# 基于tornado搭建Web服务
#
# @author eyangmeng@163.com
import sys
import time
import tornado
import tornado.ioloop
import tornado.web
from tornado.escape import json_encode
# 处理request编码问题
reload(sys)
sys.setdefaultencoding('utf8')
if __name__ == "__main__":
# 定义服务端口
server_port = "6060"
server = WebServerApplication(server_port, TimeUtils())
print "begin server"
server.process()
服务验证
到此次我们已经利用Tornado搭建起来时间转换的服务,实现时间戳和时间字符串的转换,现在我们来验证一下我们搭建的Web服务。
时间字符串转时间戳
浏览器请求
http://localhost:6060/time?time=2018-08-14 09:10:00
输出结果
{
status_code: 0,
status_msg: "ok",
cost_time: 0,
response: {
timestamp: 1534209000
}
}
时间戳转时间字符串
浏览器请求
http://localhost:6060/timestamp?timestamp=1534209000
输出结果
{
status_code: 0,
status_msg: "ok",
cost_time: 0,
response: {
time: "2018-08-14 09:10:00"
}
}
总结
本文基于Tornado实现了时间戳和时间字符串转换的Web服务,了解了简单Web服务的搭建过程。