目录:Tornado其他篇

01: tornado基础篇

02: tornado进阶篇

03: 自定义异步非阻塞tornado框架

04: 打开tornado源码剖析处理过程

目录:

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基础篇的更多相关文章

  1. 01: Django基础篇

    目录:Django其他篇 01:Django基础篇 02:Django进阶篇 03:Django数据库操作--->Model 04: Form 验证用户数据 & 生成html 05:Mo ...

  2. 02: tornado进阶篇

    目录:Tornado其他篇 01: tornado基础篇 02: tornado进阶篇 03: 自定义异步非阻塞tornado框架 04: 打开tornado源码剖析处理过程 目录: 1.1 自定制t ...

  3. 鸿蒙内核源码分析(汇编基础篇) | CPU在哪里打卡上班? | 百篇博客分析OpenHarmony源码 | v22.01

    百篇博客系列篇.本篇为: v22.xx 鸿蒙内核源码分析(汇编基础篇) | CPU在哪里打卡上班 | 51.c.h .o 硬件架构相关篇为: v22.xx 鸿蒙内核源码分析(汇编基础篇) | CPU在 ...

  4. 《量化投资:以MATLAB为工具》连载(2)基础篇-N分钟学会MATLAB(中)

    http://www.matlabsky.com/thread-43937-1-1.html   <量化投资:以MATLAB为工具>连载(3)基础篇-N分钟学会MATLAB(下)     ...

  5. Java多线程系列--“基础篇”11之 生产消费者问题

    概要 本章,会对“生产/消费者问题”进行讨论.涉及到的内容包括:1. 生产/消费者模型2. 生产/消费者实现 转载请注明出处:http://www.cnblogs.com/skywang12345/p ...

  6. Java多线程系列--“基础篇”04之 synchronized关键字

    概要 本章,会对synchronized关键字进行介绍.涉及到的内容包括:1. synchronized原理2. synchronized基本规则3. synchronized方法 和 synchro ...

  7. Java多线程系列--“基础篇”02之 常用的实现多线程的两种方式

    概要 本章,我们学习“常用的实现多线程的2种方式”:Thread 和 Runnable.之所以说是常用的,是因为通过还可以通过java.util.concurrent包中的线程池来实现多线程.关于线程 ...

  8. Java多线程系列--“基础篇”03之 Thread中start()和run()的区别

    概要 Thread类包含start()和run()方法,它们的区别是什么?本章将对此作出解答.本章内容包括:start() 和 run()的区别说明start() 和 run()的区别示例start( ...

  9. Java多线程系列--“基础篇”05之 线程等待与唤醒

    概要 本章,会对线程等待/唤醒方法进行介绍.涉及到的内容包括:1. wait(), notify(), notifyAll()等方法介绍2. wait()和notify()3. wait(long t ...

随机推荐

  1. OpenCV学习笔记之课后习题练习3-3

    3.3 创建一个100*100的拥有三个通道的二维字节类型矩阵,将其元素全部置0.通过cvPtr2D函数将指针指向中间通道(绿色),以(20,5)和(40,20)为顶点间画一个绿色的长方形. cvPt ...

  2. c++从文件中读取一行数据并保存在数组中

    从txt文本中读取数据存入数组中 #include <iostream> #include <fstream> #include <string> #include ...

  3. HDU 2602 - Bone Collector - [01背包模板题]

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2602 Many years ago , in Teddy’s hometown there was a ...

  4. (转载)准确率(accuracy),精确率(Precision),召回率(Recall)和综合评价指标(F1-Measure )-绝对让你完全搞懂这些概念

    自然语言处理(ML),机器学习(NLP),信息检索(IR)等领域,评估(evaluation)是一个必要的工作,而其评价指标往往有如下几点:准确率(accuracy),精确率(Precision),召 ...

  5. CodeForces - 779D String Game 常规二分

    题意:给你两个串,S2是S1 的一个子串(可以不连续).给你一个s1字符下标的一个排列,按照这个数列删数,问你最多删到第几个时S2仍是S1 的一个子串. 题解:二分删掉的数.判定函数很好写和单调性也可 ...

  6. Wireless Network--poj2236(并查集)

    Description An earthquake takes place in Southeast Asia. The ACM (Asia Cooperated Medical team) have ...

  7. 【JMeter】1.9上考试jmeter测试调试

    1.打开抓包工具开始抓包,抓取录制脚本的整个过程.以方便后续确认关联参数的左右关联,搜索相关代码. 1.用badboy录制测试脚本并存为jmeter格式. 2.用jmeter打开已经保存的脚本 1.用 ...

  8. Ubuntu Kylin 14.04 安装配置 jdk、eclipse、tomcat 通用

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/qq1053781225/article/details/24810107 一.安装jdk       ...

  9. awesome go library 库,推荐使用的golang库

    https://github.com/avelino/awesome-go https://github.com/spf13/cobra                        # A Comm ...

  10. No message body writer has been found for class com.alibaba.fastjson.JSONObject, ContentType: */*

    1:当使用 cxf 发布服务时,要求返回值类型为xml,或者json等 @Path("/searchProductByText") @GET @Produces({"ap ...