01: tornado基础篇
目录:Tornado其他篇
目录:
- 1.1 Tornado安装与基本使用
- 1.2 tornado各种url写法
- 1.3 配置settings & 获取get,post请求
- 1.4 tornado渲染
- 1.5 自定义UIMethod和UIModule: 类似于djando中simple_tag和自定义filter
- 1.6 模板继承
- 1.7 tornado多文件上传
- 1.8 @gen.coroutine实现异步非阻塞举例及原理解析
1.1 Tornado安装与基本使用返回顶部
1、 安装tornado
1、pip3安装
pip3 install tornado
2、源码安装
https://pypi.python.org/packages/source/t/tornado/tornado-4.3.tar.gz
2、tornado概述
1、Tornado 是 FriendFeed 使用的可扩展的非阻塞式 web 服务器及其相关工具的开源版本
2、Tornado 和现在的主流 Web 服务器框架(包括大多数 Python 的框架)有着明显的区别:它是非阻塞式服务器,而且速度相当快。
3、得利于其 非阻塞的方式和对 epoll 的运用,Tornado 每秒可以处理数以千计的连接
4、我们开发这个 Web 服务器的主要目的就是为了处理 FriendFeed 的实时功能 ——在 FriendFeed 的应用里
每一个活动用户都会保持着一个服务器连接。
3、tornado快速上手
1、使用pycharm创建一个普通项目s131415文件夹,并创建文件s131415/app.py
2、在app.py中粘贴下列内容,运行app.py文件
3、在浏览器中访问: http://127.0.0.1:8888/index 即可看到“Hello, world!!”请求内容
import tornado.ioloop
import tornado.web #1、 处理访问/index/的get请求: http://127.0.0.1:8888/index/
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("I am index!!")
# self.redirect('http://www.baidu.com')
# self.render('index.html',k1='v1') #2、 处理访问 /login/的post请求和get请求: http://127.0.0.1:8888/login/
class LoginHandler(tornado.web.RequestHandler):
def get(self):
self.write('login')
def post(self,*args,**kwargs):
self.write('login post') #3、 配置settings
settings = {
'template_path': 'template', # 配置html文件模板位置
'static_path': 'static', # 配置静态文件路径(图片等)
'static_url_prefix': '/static/', # 前端引入静态文件路径
} #4 路由系统
application = tornado.web.Application([
(r"/index/", MainHandler),
(r"/login/", LoginHandler),
],**settings) #5 启动这个tornado这个程序
if __name__ == "__main__":
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()
tornado基本使用
1.2 tornado各种url写法返回顶部
1、无正则匹配url (http://127.0.0.1:8000/index/?nid=1&pid=2)
import tornado.ioloop
import tornado.web class MainHandler(tornado.web.RequestHandler):
def get(self):
nid = self.get_query_argument('nid')
pid = self.get_query_argument('pid')
self.write("Hello, world") # http://127.0.0.1:8000/index/?nid=1&pid=2
application = tornado.web.Application([
(r"/index/", MainHandler),
]) if __name__ == "__main__":
application.listen(8000)
tornado.ioloop.IOLoop.instance().start()
app.py
2、基于(\d+)正则的url
import tornado.ioloop
import tornado.web class MainHandler(tornado.web.RequestHandler):
def get(self,nid,pid):
print(nid,pid)
self.write("Hello, world") # http://127.0.0.1:8000/index/1/2/
application = tornado.web.Application([
(r"/index/(\d+)/(\d+)/", MainHandler), # 这种只能传数字
# (r"/index/(\w+)/(\w+)/", MainHandler), # 这种可以传数字、字母、下划线
]) if __name__ == "__main__":
application.listen(8000)
tornado.ioloop.IOLoop.instance().start()
app.py
3、基于正则分组(?P<nid>\d+),可以不考虑接收参数顺序 (推荐)
import tornado.ioloop
import tornado.web class MainHandler(tornado.web.RequestHandler):
def get(self,nid,pid):
print(nid,pid)
self.write("Hello, world") # http://127.0.0.1:8000/index/1/2/
application = tornado.web.Application([
(r"/index/(?P<nid>\d+)/(?P<pid>\d+)/", MainHandler), # 这种只能传数字
]) if __name__ == "__main__":
application.listen(8000)
tornado.ioloop.IOLoop.instance().start()
app.py
1.3 配置settings & 获取get,post请求返回顶部
1、settings可配置参数
settings = {
'template_path': 'template', #配置html文件模板位置
'static_path': 'static', #配置静态文件路径(图片等)
'static_url_prefix': '/static/', #前端引入静态文件路径
'ui_methods': mt,
'ui_modules': md, 'xsrf_cookies':True,
'cookie_secret':'xxx',
'login_url':"/auth/login",
'autoescape':None,
'local':"zh_CN",
'debug':True,
}
tornado中settings字典可配置参数
2、获取get、post请求
import tornado.ioloop
import tornado.web #1、 处理访问/index/的get请求: http://127.0.0.1:9999/index
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("I am index!!")
# self.redirect('http://www.baidu.com')
# self.render('index.html',k1='v1') #2、 处理访问 /login/的post请求和get请求: http://127.0.0.1:9999/login
class LoginHandler(tornado.web.RequestHandler):
def get(self): #2.1 获取url中以get方式传递过来的数据: http://127.0.0.1:9999/login/?username=zhangsan
# print(self.get_query_argument('username')) # zhangsan
# print(self.get_query_arguments('username')) # ['zhangsan']
# print( self.get_argument('username') ) # get和post两种请求传递的数据都能获取 self.render('login.html')
def post(self,*args,**kwargs): #2.2 获取请求体中以post传递的数据
# print( self.get_body_argument('faver') ) # 仅能获取单选,多选仅能获取最后一个
# print( self.get_body_arguments('faver') ) # ['1', '2', '3'] 获取多选 #2.3 get和post两种请求传递的数据都能获取
# print( self.get_argument('username') ) #2.4 设置和获取cookie
# self.cookies
# self.set_cookie() #2.5 设置和获取请求头
# self._headers
# self.get_header() self.write('login post') #3、 配置settings
settings = {
'template_path': 'template', # 配置html文件模板位置
'static_path': 'static', # 配置静态文件路径(图片等)
'static_url_prefix': '/static/', # 前端引入静态文件路径
} #4 路由系统
application = tornado.web.Application([
(r"/index/", MainHandler),
(r"/login/", LoginHandler),
],**settings) #5 启动这个tornado这个程序
if __name__ == "__main__":
application.listen(9999)
tornado.ioloop.IOLoop.instance().start()
app.py
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="/static/base.css">
</head>
<body>
<form method="POST" action="/login/">
<input type="text" name="username"> <h5 class="c1">多选</h5>
男球:<input type="checkbox" name="faver" value="1" />
足球:<input type="checkbox" name="faver" value="2" />
皮球:<input type="checkbox" name="faver" value="3" />
<input type="submit" value="提交">
</form>
</body>
</html>
/template/login.html
.c1{
color: red;
}
/template/base.css
1.4 tornado渲染返回顶部
1、for循环
import tornado.ioloop
import tornado.web class MainHandler(tornado.web.RequestHandler):
def get(self):
self.render("index.html", username='tom',list_info=[11, 22, 33],user_dic={'username':'zhangsan','age':77}) application = tornado.web.Application([
(r"/index", MainHandler),
]) if __name__ == "__main__":
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()
app.py
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h3>用户名:{{username}}</h3>
{% for item in list_info %}
<li>{{item}}</li>
{% end %}
<p></p>
{% for item in user_dic %}
<li>{{item}} : {{user_dic[item]}}</li>
{% end %}
</body>
</html>
index.html
2、if、in、判断相等
import tornado.ioloop
import tornado.web class MainHandler(tornado.web.RequestHandler):
def get(self):
self.render("index.html", list_info=[11, 22, 33],username='tom') application = tornado.web.Application([
(r"/index", MainHandler),
]) if __name__ == "__main__":
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()
app.py
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{% if 11 in list_info %}
true
{% else %}
false
{% end %} {% if username == "tom" %}
my name is {{username}}
{% else %}
not tom
{% end %}
</body>
</html>
index.html
1.5 自定义UIMethod和UIModule: 类似于djando中simple_tag和自定义filter 返回顶部
1、UIModule与UIMethod比较
1. UIModule: 可以传参、可以生成html、css、js代码
2. UIMethod: 这个不能传参数,不能生成css,js等,只能生成html文件
2、UIModule和UIMethod使用举例
import tornado.ioloop
import tornado.web
from tornado.escape import linkify
import uimodules as md #1.导入uimodules模块
import uimethods as mt #2.导入uimethods模块 class MainHandler(tornado.web.RequestHandler):
def get(self):
self.render('index.html')
settings = {
'template_path': 'template',
'static_path': 'static',
'static_url_prefix': '/static/',
'ui_methods': mt, #3.将uimethods模块注册到settings中
'ui_modules': md, #4.将uimodules模块注册到settings中
} application = tornado.web.Application([
(r"/index", MainHandler),
], **settings) if __name__ == "__main__":
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()
app.py注册
from tornado.web import UIModule
from tornado import escape # uimodule不仅可以帮生成标签,还可以帮添加css,js样式
class custom(UIModule):
# def javascript_files(self):
# '''1、生成: <script src="base.js"></script> '''
# return ['base.js','header.js']
#
# def embedded_javascript(self):
# '''2、生成: <script> alert(123); </script> '''
# return "alert(123);"
#
# def css_files(self):
# '''3、在头部生成: <link rel="stylesheet" href="base.css">'''
# return ['base.css','header.css']
#
# def embedded_css(self):
# '''4、在头部style标签生成: <style> .c1{ color:red; } </style>'''
# return ".c1{color:red;}" def render(self, *args, **kwargs):
'''5、生成html文件'''
return escape.xhtml_escape('<h1>tom</h1>')
uimodules.py定义
def tab(self):
return '<h1>tom</h1>'
uimethods.py定义
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>hello</h1>
<p>{% module custom(123) %}</p> {{ tab() }}
</body>
</html>
index.html使用
1.6 模板继承返回顶部
1、模板继承使用
1. 在master.html中定义模板: {% block css %} {% endblock %}
2. 在子类中引入要继承的模板: {% extends 'layout.html' %}
2、模板导入
1. 使用时直接导入即可: {% include "header.html" %}
import tornado.ioloop
import tornado.web class MainHandler(tornado.web.RequestHandler):
def get(self):
self.render("index.html") settings = {
'template_path':'template',
'static_path':'static',
'static_url_prefix':'/static/',
} application = tornado.web.Application([
(r"/index/", MainHandler),
],**settings) if __name__ == "__main__":
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()
app.py
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<title>{% block title %}Default title{% end %}</title> <link rel="stylesheet" href="/static/css/base.css">
{% block css %}{% end %} </head>
<body>
<div class="c1">这里是layout.html这个母版中的内容</div>
{% block RenderBody %}{% end %}
</body>
</html>
layout.html 母版文件
{% extends 'layout.html'%}
{% block css %}<link rel="stylesheet" href="/static/css/index.css">{% end %} {% block RenderBody %}
<h3 class="c1">这个RenderBody块继承的是header.html这个母版</h3> <div>
{% include 'header.html' %}
</div>
{% end %}
index.html 子版中引入母版
<h3>
这里是header.html中的内容,需要导入的文件
</h3>
header.html 被导入的文件
1.7 tornado多文件上传 返回顶部
import tornado.ioloop
import tornado.web class MainHandler(tornado.web.RequestHandler):
def get(self):
self.render('index.html') def post(self, *args, **kwargs):
file_metas = self.request.files["fff"]
for meta in file_metas:
file_name = meta['filename']
with open(file_name,'wb') as up:
print('hahah')
up.write(meta['body']) settings = {
'template_path': 'template',
} application = tornado.web.Application([
(r"/index", MainHandler),
], **settings) if __name__ == "__main__":
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()
app.py
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<title>上传文件</title>
</head>
<body>
<form id="my_form" name="form" action="/index" method="POST" enctype="multipart/form-data" >
<input name="fff" id="my_file" type="file" />
<input type="submit" value="提交" />
</form>
</body>
</html>
index.html
1.8 @gen.coroutine实现异步非阻塞举例及原理解析返回顶部
1、tornado.gen.coroutine和tornado.web.asynchronous比较
1. @tornado.web.asynchronous 实现长连接,调用self.finish()才结束
2. @tornado.gen.coroutine 这个实现异步
3. 你要想异步,就要保持长连接,否则你的handler执行完就自己return了
4. @asynchronous会监听@gen.coroutine的返回结果(Future),并在@gen.coroutine装饰的代码段执行完成后自动调用finish。
5. 从Tornado 3.1版本开始,只使用@gen.coroutine就可以了。
2、tornado实现异步原理
1. 每个请求过来就会创建一个socket对象,并yield一个future对象,然后tornado就处理下一个连接了
2. tornado内部会以socket对象为key,future对象为value加入字典
3. tornado内部调用epoll方法监听这个全局字典,有socket对象变化就会执行future.set_result('...')
4. 执行future.set_result('...')后就会将future.ready标志位变成True,然后就会调用callback方法返回内容
注1:yield 一个 Future对象,那么Tornado会等待,直到执行future.set_result('...')才会释放
注2:epoll实质是不断的轮询所负责的所有socket,当某个socket有数据到达了,就通知用户进程
import tornado.ioloop
import tornado.web
from tornado import gen class IndexHandler(tornado.web.RequestHandler):
@gen.coroutine
def get(self):
self.write('I am index!!') application = tornado.web.Application([
(r"/index/", IndexHandler),
]) if __name__ == "__main__":
print('http://127.0.0.1:8888/index/')
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()
tornado实现异步非阻塞举例
#! /usr/bin/env python
# -*- coding: utf-8 -*-
import tornado.ioloop
import tornado.web
from tornado import gen
from tornado.concurrent import Future future = None
class IndexHandler(tornado.web.RequestHandler):
@gen.coroutine
def get(self):
global future
future = Future()
future.add_done_callback(self.doing)
yield future def doing(self,*args,**kwargs):
self.write('async')
self.finish() class StopHandler(tornado.web.RequestHandler):
def get(self):
future.set_result('.......') application = tornado.web.Application([
(r"/index/", IndexHandler),
(r"/stop/", StopHandler),
]) if __name__ == "__main__":
print('http://127.0.0.1:8888/index/')
application.listen(8888)
tornado.ioloop.IOLoop.instance().start() '''
http://127.0.0.1:8888/index/ # 只要不返回数据,浏览器就不会返回一直等着保持长连接
http://127.0.0.1:8888/stop/ # 访问/stop/是会调用future.set_result()此时 /index/就会返回数据
'''
使用Future对象模拟tornado异步非阻塞简单原理
01: tornado基础篇的更多相关文章
- 01: Django基础篇
目录:Django其他篇 01:Django基础篇 02:Django进阶篇 03:Django数据库操作--->Model 04: Form 验证用户数据 & 生成html 05:Mo ...
- 02: tornado进阶篇
目录:Tornado其他篇 01: tornado基础篇 02: tornado进阶篇 03: 自定义异步非阻塞tornado框架 04: 打开tornado源码剖析处理过程 目录: 1.1 自定制t ...
- 鸿蒙内核源码分析(汇编基础篇) | CPU在哪里打卡上班? | 百篇博客分析OpenHarmony源码 | v22.01
百篇博客系列篇.本篇为: v22.xx 鸿蒙内核源码分析(汇编基础篇) | CPU在哪里打卡上班 | 51.c.h .o 硬件架构相关篇为: v22.xx 鸿蒙内核源码分析(汇编基础篇) | CPU在 ...
- 《量化投资:以MATLAB为工具》连载(2)基础篇-N分钟学会MATLAB(中)
http://www.matlabsky.com/thread-43937-1-1.html <量化投资:以MATLAB为工具>连载(3)基础篇-N分钟学会MATLAB(下) ...
- Java多线程系列--“基础篇”11之 生产消费者问题
概要 本章,会对“生产/消费者问题”进行讨论.涉及到的内容包括:1. 生产/消费者模型2. 生产/消费者实现 转载请注明出处:http://www.cnblogs.com/skywang12345/p ...
- Java多线程系列--“基础篇”04之 synchronized关键字
概要 本章,会对synchronized关键字进行介绍.涉及到的内容包括:1. synchronized原理2. synchronized基本规则3. synchronized方法 和 synchro ...
- Java多线程系列--“基础篇”02之 常用的实现多线程的两种方式
概要 本章,我们学习“常用的实现多线程的2种方式”:Thread 和 Runnable.之所以说是常用的,是因为通过还可以通过java.util.concurrent包中的线程池来实现多线程.关于线程 ...
- Java多线程系列--“基础篇”03之 Thread中start()和run()的区别
概要 Thread类包含start()和run()方法,它们的区别是什么?本章将对此作出解答.本章内容包括:start() 和 run()的区别说明start() 和 run()的区别示例start( ...
- Java多线程系列--“基础篇”05之 线程等待与唤醒
概要 本章,会对线程等待/唤醒方法进行介绍.涉及到的内容包括:1. wait(), notify(), notifyAll()等方法介绍2. wait()和notify()3. wait(long t ...
随机推荐
- PAT天梯赛L2-003 月饼【贪心】
L2-003. 月饼 时间限制 100 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 月饼是中国人在中秋佳节时吃的一种传统食品,不同地区有许多不 ...
- 使用keras导入densenet模型
从keras的keras_applications的文件夹内可以找到内置模型的源代码 Kera的应用模块Application提供了带有预训练权重的Keras模型,这些模型可以用来进行预测.特征提取和 ...
- PAT-GPLT L1-035 - 情人节 - [大水题]
题目链接:https://www.patest.cn/contests/gplt/L1-035 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standar ...
- 江南大学第三届程序设计竞赛K题 - Cun Tou Gaming - [贪心+堆]
描述 CTG(Cun Tou Gaming) 是我校的一支 LOL 战队,他们参加比赛总是可以拿到冠军,因为每次都只有他们一支队伍参赛,所以只需要去签个到就可以直接夺冠并领取奖金.现在有 n 场比赛 ...
- python中super的使用方法
说白了,super的使用就是要子类要调用父类的方法,我们就用super,那你要有调用的规范,我们明白这个规范就可以了. 在python2和python3中,调用方法不同,注意就是了.Python3.x ...
- web前端开发笔记(1)
一.HTML标签书写有哪些规范? 页面编码. 文档声明. 关键字与描述. 行内元素不能包含块级元素. a标签不能嵌套a标签. 标签名和属性必须用小写字母书写,属性必须加引号,标签必须闭合,单标签页必 ...
- 堆内存泄漏移除导致tcp链接异常高
故障现象: 1:活动前端Nginx服务器TCP连接数到1万多 2:活动后端Tomcat其中1台TCP连接数达4千,并且CPU瞬间到780%(配置8核16G),内存正常 3:重启后端Tomcat后,TC ...
- windows7系统下让所有文件夹都使用同一种视图的方法
Windows7系统可以对每个文件夹进行个性化视图设置,可以根据自己的个人喜好和实际需要更改文件或文件夹图标的大小,或者让文件或文件夹以列 表.平铺等方式显示.但是,如果你对N个文件夹视图进行了风格各 ...
- AWTK 全称为 Toolkit AnyWhere,是 ZLG 倾心打造的一套基于 C 语言开发的 GUI 框架(三平台+2个手机平台+嵌入式)
最终目标: 支持开发嵌入式软件. 支持开发Linux应用程序. 支持开发MacOS应用程序. 支持开发Windows应用程序. 支持开发Android应用程序. 支持开发iOS应用程序. 支持开发2D ...
- 洛谷P3599 Koishi Loves Construction 构造
正解:构造 解题报告: 传送门! 这题俩问嘛,就分成两个问题港QwQ 就按顺序趴,先港第一问QwQ 首先要发现,n在膜n意义下就是0嘛 那作为前缀和的话显然它就只能放在第一个 然后再想下,发现,如果n ...