目录: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. Oracle安装部署之dbca静默建库和删除库

    dbca查看帮助: [oracle@wen ~]$ dbca -help 1).运行静默建库语句 [oracle@wen ~]$ dbca -silent -cloneTemplate -gdbNam ...

  2. 选择排序之python

    选择排序( Selection sort) 1.算法描述: 通过n-i次关键字之间的比较,从n-i+1个记录中选出关键字最小的记录,并和第i(1<=i<=n)个记录进行交换. 对尚未完成排 ...

  3. linux中使用arcpy

    切换到对应目录   即下图的  server安装路径  /home/arcgis/arcgis/server/tools 然后输入 ./python  (这一步要注意    python这个命令    ...

  4. 学习计划 mysql 主从复制

    网上资料繁多,需要跳多少坑才能实现,跳跳就知道了. -- 主从复制 如题:主数据库进行的操作,从数据库进行备份. -- 原理 有关于这方面的原理网上也是一搜一大片,去看看吧.肯定没错. 这里简单说一下 ...

  5. 学习计划 mysql 用户管理与权限

    最近在学习数据库的 主从复制 里面涉及到了关于用户及其管理权限的赋予,之前一直没有认真的学习这个. 现在想具体的学习一下. -- 为什么 数据库 要实现多用户管理? 举个最简单的例子,你需要和第三方做 ...

  6. CentOS安装Jdk并配置环境变量

    环境 CentOS7.2 (安装镜像CentOS-7-x86_64-DVD-1611) 目标 在CentOS7.2上安装jdk1.8(tar.gz安装包),并配置环境变量 jdk安装在/home/so ...

  7. 【转】锁(lock)知识及锁应用

    sql server锁(lock)知识及锁应用转自:http://blog.csdn.net/huwei2003/article/details/4047191 关键词:锁提示,锁应用 提示:这里所摘 ...

  8. 前端 HTML body标签相关内容 常用标签 换行标签 br

    换行标签 <br> <br>标签用来将内容换行,其在HTML网页上的效果相当于我们平时使用word编辑文档时使用回车换行. 在第一行中间加上br <!DOCTYPE ht ...

  9. [py][mx]django通过邮箱找回密码

    忘记密码处理流程 注意: 这个文章里的找回密码页面截取有问题. 找回密码页应该是让输入邮箱 直接上代码 class ActiveView(View): # 主要功能是修改user_profile里的i ...

  10. Git warning:LF will be replaced by CRLF in readme.txt的原因与解决方案

    今天用Git bash遇到的问题,看了几个回答之后发现一个比较有价值的,给大家分享一下,其他很多的回答都有很或多或少存在一些弊端. 原回答地址在stackoverflow上,附上链接--http:// ...