tornado网站
1.1 Tornado是什么?¶
Tornado是使用Python编写的一个强大的、可扩展的Web服务器。它在处理严峻的网络流量时表现得足够强健,但却在创建和编写时有着足够的轻量级,并能够被用在大量的应用和工具中。
我们现在所知道的Tornado是基于Bret Taylor和其他人员为FriendFeed所开发的网络服务框架,当FriendFeed被Facebook收购后得以开源。不同于那些最多只能达到10,000个并发连接的传统网络服务器,Tornado在设计之初就考虑到了性能因素,旨在解决C10K问题,这样的设计使得其成为一个拥有非常高性能的框架。此外,它还拥有处理安全性、用户验证、社交网络以及与外部服务(如数据库和网站API)进行异步交互的工具。
这是4s店与客户的保养和推送图:
二,安装tornado
先打开CMD 进入E盘放的env(环境文件)
- E: 2. cd env 3.virtualenv(创建虚拟环境)
4.virtualenv --no-site-packages tornadoenv9 (创建环境包)
5.cd tornadoenv9 6. cd Scripts 7.activate 8.pip install tornado
import os
from datetime import datetime, timedelta
import pymysql
import tornado.ioloop
import tornado.web
from tornado.options import define, options, parse_command_line
# 定义默认启动的端口port为80, type不写int会报错,不然返回的是字符串
define('port', default=80, type=int)
class MainHandler(tornado.web.RequestHandler):
# 必须继承RequestHandler
def get(self):
# 接收参数(取值)
name = self.get_argument('name')
# name = self.get_query_argument('name') # 和上面一样
# 渲染响应给浏览器的数据
self.write('hello tornado!')
def post(self):
# 接收参数(取值)
name = self.get_argument('name')
name = self.get_query_argument('name')
# 渲染响应给浏览器的数据
self.write('hello tornado post')
class ResHandler(tornado.web.RequestHandler):
def get(self):
# make_response('....', 404)
self.write('今天天气真好
')
# 设置响应页面状态码
self.set_status(200)
# self.cookies 拿到所有的cookies
# 设置cookie, 其中的expire参数表示过期时间,到了过期时间,自动删除
self.set_cookie('token', '12234', expires_days=1)
# 明天的现在
out_time = datetime.now() + timedelta(days=1) # 和上面一样
self.set_cookie('token123', '123456', expires=out_time)
# 删除cookie中的token值
# self.clear_cookie('token')
# self.clear_all_cookies()
# 跳转
self.redirect('/') # /res/变成/ 400: Bad Request
# 假如顺序是month, year, day 若改变就变了 结果就是这样:11年2019月21日
class DaysHandler(tornado.web.RequestHandler):
def get(self, year, month, day):
self.write('%s年%s月%s日' % (year, month, day))
# 顺序无所谓
class Days2Handler(tornado.web.RequestHandler):
def get(self, month, year, day):
self.write('%s年%s月%s日' % (year, month, day))
# get - 只负责获取(查询)数据
def post(self, month, year, day):
self.write('post: 只负责新增数据')
def delete(self, month, year, day):
self.write('delete: 只负责删除')
def patch(self, month, year, day):
self.write('patch: 修改部分属性')
def put(self, month, year, day):
self.write('put: 修改全部数据')
class EntryHandler(tornado.web.RequestHandler):
# initialize开始就进行了调用
def _initialize(self):
self.conn = pymysql.Connection(host='127.0.0.1', password='root',
database='flask9', user='root',
port=3306)
self.cursor = self.conn.cursor()
print('initialize')
# prepare和initialize意义差不多 都是开始就执行
def prepare(self):
print('prepare')
def get(self):
print('get')
# 实现功能是,访问flask9数据库,查询出学生的所有信息
conn = pymysql.Connection(host='127.0.0.1', password='root',
database='flask9', user='root',
port=3306)
cursor = conn.cursor()
# 执行 查询
sql = 'select * from stu;'
cursor.execute(sql)
data = cursor.fetchall()
print(data)
# 关闭游标
conn.close()
self.write('查询数据')
def post(self):
pass
def on_finish(self):
# 最后执行的方法
print('on_finish')
self.conn.close()
class IndexHandler(tornado.web.RequestHandler):
def get(self):
# 渲染页面
self.render('index.html') # 此时index.html默认是和hello.py文件同级的(会报错),所以我们需要找到路径(os)修改路径(template_path)
def make_app():
# handlers参数中定义路由匹配地址
return tornado.web.Application(handlers=[
(r'/', MainHandler),
(r'/res/', ResHandler),
(r'/days/(\d{4})/(\d{2})/(\d{2})/', DaysHandler),
(r'/days2/(?P\d{4})/(?P\d{2})/(?P\d{2})/', Days2Handler),
(r'/entry_point/', EntryHandler),
(r'/index/', IndexHandler)
],
template_path=os.path.join(os.path.dirname(os.path.abspath(__file__)), 'templates')) # MainHandler调用上面的类 /是路径, \这是正则里面的 temp需要先获取路径,所以导入os
# 指定模板文件路径, 就是到这个templates文件, 不然就是day01文件,这样会报错
if __name__ == '__main__':
# os是用于找路径的 abspath(绝对路径) __file__ 指当前文件
# print(os.path.dirname(os.path.abspath(__file__))) # os.path.dirname() 上层路径
# a = (os.path.dirname(os.path.abspath(__file__)))
# print(os.path.join(a, 'templates'))
# 解析启动命令, python xxx.py --port 端口号
parse_command_line()
# 启动
app = make_app()
# 监听端口
app.listen(options.port)
# 监听启动的IO实例
tornado.ioloop.IOLoop.current().start()
3. 基于tornado的最简单应用
创建FirstTornado.py文件
import tornado.ioloop
import tornado.web
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello, world")
def make_app():
return tornado.web.Application(handlers=[
(r"/hello", MainHandler),
])
if __name__ == "__main__":
app = make_app()
app.listen(8888)
tornado.ioloop.IOLoop.current().start()
运行:python FirstTornado.py
如下进行详细讲解每一行代码的含义,如下:
** 编写一个Tornado应用中最多的工作是定义类继承Tornado的RequestHandler类。在这个例子中,我们创建了一个简单的应用,在给定的端口监听请求,并在路由("/hello")响应请求。**
你可以在命令行里尝试运行这个程序以测试输出:
python hello.py
现在你可以在浏览器中打开http://localhost:8888/hello,
3.1 代码分析
示例中编写的Tornado应用没有使用任何Tornado的异步功能,只是定义了一个MainHandler类,并继承了Tornado的RequestHandler类。
示例代码分析如下:
1) MainHandler类:
MainHandler类是Tornado的请求处理函数类,当处理一个请求时,Tornado会实例化这个类,并调用与HTTP请求方法所对应的方法。在示例中的MainHandler类中定义了get方法,也就是说当HTTP请求方式为GET时,MainHandler中的get方法将会被调用并作出响应。
2)self.write()方法
以一个字符串作为函数的参数,将字符串写入到HTTP响应中。
3)make_app()方法
返回一个Tornado的Application类的实例,传递给Application类的__init__方法中的最重要的参数就是handlers,该参数表示告知Tornado应用应该调用那个类来处理响应。比如本例子中想调用MainHandler中的get方法,则应该访问[http://127.0.0.1:8888/hello地址。](http://127.0.0.1:8888/hello%E5%9C%B0%E5%9D%80%E3%80%82)
4) app.listen(8888)
Application对象被创建后,可以调用listen()方法来监听端口。如本例子中监听的端口为8888。
5)tornado.ioloop.IOLoop.current().start()
用于创建一个Tornado的IOLoop的实例,并一直运行Tornado项目,用于接收处理客户端的访问请求。
在虚拟环境tornadoenv中运行FirstTornado.py文件,然后在浏览器中访问http://127.0.0.1:8888/hello地址
4. 修改启动方式,使用命令行参数启动服务
修改最简单的tornado程序,命名为helloTornado2.py。 如下:
import tornado.ioloop
import tornado.web
from tornado.options import define, options, parse_command_line
# 定义默认的端口
define('port', default=8000, type=int)
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello, world")
def make_app():
return tornado.web.Application(handlers=[
(r"/hello", MainHandler),
])
if __name__ == "__main__":
# 解析命令行
parse_command_line()
# 获取Application对象
app = make_app()
# 监听端口
app.listen(options.port)
# 启动IOLoop实例
tornado.ioloop.IOLoop.current().start()
** Tornado中包含了一个有用的读取命令行的模块(tornado.options),可以使用tornado.options模块来指定应用监听HTTP请求的端口。**
# 读取命令行中的配置
from tornado.options import define, options, parse_command_line
# 定义默认的端口
define('port', default=8000, type=int)
导入tornado.options的define函数,define函数中接收了三个参数,分析如下:
1)第一个参数‘port’
表示定义的port参数将成为全局options的一个属性。
2)第二个参数default
表示port属性的默认值,默认值为8000。如果在启动命令行中没有指定port参数,则项目启动的端口默认为8000。如果在启动命令行中指定了port参数,则使用命令行中的参数作为项目启动的端口。
3)第三个参数type
用于做参数类型的校验,当不适合的参数类型被给予时会抛出异常。示例中指定type为int类型,则表示命令行中的指定的port参数必须为整型。
启动并运行helloTornado2.py
python helloTornado2.py --port=8888