Python之tornado
一、快速了解Tornado框架
1)tornado简介
Tornado 和现在的主流 Web 服务器框架(包括大多数 Python 的框架)有着明显的区别:它是非阻塞式服务器,而且速度相当快。得利于其 非阻塞的方式和对epoll的运用,Tornado 每秒可以处理数以千计的连接,因此 Tornado 是实时 Web 服务的一个 理想框架。我们开发这个 Web 服务器的主要目的就是为了处理 FriendFeed 的实时功能 ——在 FriendFeed 的应用里每一个活动用户都会保持着一个服务器连接 FriendFeed是一个聚合个人信息的网站,可集成网络社区媒体、社交网络服务、书签网站、博客、微博客的更新,及其他RSS/Atom信源 安装 pip install tornado
Tornado和安装
2)tornado框架快速上手
import tornado.ioloop
import tornado.web class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello, world") application = tornado.web.Application([
(r"/index", MainHandler),
]) if __name__ == "__main__":
application.listen()
tornado.ioloop.IOLoop.instance().start()
tornado的快速入门
执行过程
:执行脚本,监听 端口
:浏览器客户端访问 /index --> http://127.0.0.1:8888/index
:服务器接受请求,并交由对应的类处理该请求
:类接受到请求之后,根据请求方式(post / get / delete ...)的不同调用并执行相应的方法
:方法返回值的字符串内容发送浏览器
#!/usr/bin/env python
# -*- coding:utf-8 -*- import tornado.ioloop
import tornado.web
from tornado import httpclient
from tornado.web import asynchronous
from tornado import gen import uimodules as md
import uimethods as mt class MainHandler(tornado.web.RequestHandler):
@asynchronous
@gen.coroutine
def get(self):
print 'start get '
http = httpclient.AsyncHTTPClient()
http.fetch("http://127.0.0.1:8008/post/", self.callback)
self.write('end') def callback(self, response):
print response.body settings = {
'template_path': 'template',
'static_path': 'static',
'static_url_prefix': '/static/',
'ui_methods': mt,
'ui_modules': md,
} application = tornado.web.Application([
(r"/index", MainHandler),
], **settings) if __name__ == "__main__":
application.listen(8009)
tornado.ioloop.IOLoop.instance().start()
步非堵塞实例
二、tornado的模板语言
1)git请求,返回前端页面。render
import tornado.ioloop
import tornado.web class LoginHandler(tornado.web.RequestHandler):
def get(self):
self.render('login.html') def post(self):
self.write("Hello, world") # 生成路由规则
application = tornado.web.Application([
(r"/login", LoginHandler),
]) if __name__ == "__main__":
# 创建socket对象8888
# 将socket对象添加到select或epoll
application.listen()
# 将select或epoll开始死循环 while True
tornado.ioloop.IOLoop.instance().start()
main.py
前端页面默认同级目录
2)前端模板显示内容
import tornado.ioloop
import tornado.web class LoginHandler(tornado.web.RequestHandler):
def get(self):
# self.render('login.html')
# self.render('login.html',k1='v1')
# self.render('login.html',k1='v1',k2='v2')
# self.render('login.html',**{'k1':'v1'})
self.render('login.html',**{'k1':'v1',
'k2':[,,,],
'k3':{'name':'root','age':}}) # 生成路由规则
application = tornado.web.Application([
(r"/login", LoginHandler),
]) if __name__ == "__main__":
# 创建socket对象8888
# 将socket对象添加到select或epoll
application.listen()
# 将select或epoll开始死循环 while True
tornado.ioloop.IOLoop.instance().start()
main.py
对于前端显示
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>Login</h1>
<h3>{{k1}}</h3>
<h2>{{k2}}</h2>
<h2>{{k2[]}}</h2>
<ul>
{% for item in k2 %}
<li>{{item}}</li>
{%end%}
</ul>
<div>{{k3}}</div>
<div>{{k3['name']}}</div>
<div>{{k3.get('name')}}</div>
<ul>
{% for k,v in k3.items() %}
<li>{{k}}--{{v}}</li>
{%end%}
</ul>
</body>
</html>
login.html
前端语法常用归纳
{% for item in k2 %}
<li>{{item}}</li>
{%end%} <h2>{{k2}}</h2>
<h2>{{k2[]}}</h2>
<div>{{k3['name']}}</div>
<div>{{k3.get('name')}}</div>
3)获取用户相应信息
def get(self):
# 获取用户请求相关信息
self.get_cookie()
v = self.get_argument('p') # http://127.0.0.1:8888/login?p=123
print(v)
self.render('login.html',**{'k1':'v1',
'k2':[,,,],
'k3':{'name':'root','age':}})
有多个self,也返回给用户
4)self.set_cookies。设置额外的内容
def get(self):
# 设置额外的相应内容
self.set_cookie('k1','v1') # 设置cookies
self.set_header('h1','v1') # 设置相应头 self.render('login.html')
设置额外的内容返回用户
5)跳转。self.redirect('/login/')
6)静态文件和模板文件的配置
settings = {
'static_path':'static',
'static_url_prefix':'/sss/',
'template_path':'templates',
} application = tornado.web.Application([
(r"/login", LoginHandler),
],**settings)
main.py
前端文件引入静态文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="/sss/commons.css">
</head>
<body>
<h1>Login</h1>
</body>
</html>
html引入css
7)后台获取form表单提交的数据
<form method="POST" action="/login">
<input type="text" name="user">
<input type="submit" value="提交">
</form>
form.html
class LoginHandler(tornado.web.RequestHandler):
def get(self):
self.render('login.html')
def post(self):
v = self.get_argument('user')
print(v)
self.redirect('http://autohome.com.cn')
main.py
8)自定义函数注册,前端执行函数
def tab(self):
return 'UIMethod'
uimethods.py
settings字典注册
import uimethods as mt
settings = {
'static_path':'static',
'static_url_prefix':'/sss/',
'template_path':'templates',
'ui_methods':mt,
} application = tornado.web.Application([
(r"/login", LoginHandler),
],**settings)
前端调用函数
<body>
<h1>Login {{ tab() }}</h1>
<form method="POST" action="/login">
<input type="text" name="user">
<input type="submit" value="提交">
</form>
</body>
html
9)自定义类方法注册。可返还一般数据,css样式,css文件,js文件
from tornado.web import UIModule
from tornado import escape class Custom(UIModule):
def embedded_css(self):
return "body{color:blue;}"
def css_files(self):
return "a.sss"
def javascript_files(self):
return "a.js"
def render(self, *args, **kwargs):
return '<h1>user sb</h1>'
#return escape.xhtml_escape('<h1>user sb</h1>')
uimodules.py
settings字典注册
import uimethods as mt
import uimodules as md
settings = {
'static_path':'static',
'static_url_prefix':'/sss/',
'template_path':'templates',
'ui_methods':mt,
'ui_modules':md, }
前端调用函数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="/sss/commons.css">
</head>
<body>
<h1>Login {{ tab() }}</h1>
<h2>{% module Custom() %}</h2>
<form method="POST" action="/login">
<input type="text" name="user">
<input type="submit" value="提交">
</form>
</body>
</html>
html
三、tornado的session管理
1)基于内存的session
session文件方法
import uuid class Session(object):
container = {}
def __init__(self,handler):
# 获取用户cookies,如果有,不操作,否则给用户生成随机字符串
# - 写给用户
# - 保存在session
nid = handler.get_cookie('session_id')
if nid:
if nid in Session.container:
pass
else:
nid = str(uuid.uuid4())
Session.container[nid] = {}
else:
nid = str(uuid.uuid4())
Session.container[nid] = {}
handler.set_cookie('session_id',nid,max_age=) # max_age= 超时时间
# nid 当前访问用户的随机字符串+
self.nid = nid
# 封装了所有用户请求信息
self.handler = handler def __setitem__(self,key,value):
Session.container[self.nid][key] = value def __getitem__(self,item):
return Session.container[self.nid].get(item) def __delitem__(self, key):
del Session.container[self.nid][key]
session.py
验证session的类
import tornado.ioloop
import tornado.web class BaseHandler(object):
def initialize(self):
from session import Session
self.session = Session(self)
super(BaseHandler,self).initialize() class IndexHandler(BaseHandler,tornado.web.RequestHandler):
def get(self):
if self.session['is_login']:
self.write('Hello World')
else:
self.redirect('/login') class LoginHandler(BaseHandler,tornado.web.RequestHandler):
def get(self):
self.render('login.html')
def post(self):
v = self.get_argument('user')
if v == 'root':
self.session['is_login'] = True
self.redirect('/index')
else:
self.redirect('/login')
main.py
总的运行文件
import tornado.ioloop
import tornado.web class BaseHandler(object):
def initialize(self):
from session import Session
self.session = Session(self)
super(BaseHandler,self).initialize() class IndexHandler(BaseHandler,tornado.web.RequestHandler):
def get(self):
if self.session['is_login']:
self.write('Hello World')
else:
self.redirect('/login') class LoginHandler(BaseHandler,tornado.web.RequestHandler):
def get(self):
self.render('login.html')
def post(self):
v = self.get_argument('user')
if v == 'root':
self.session['is_login'] = True
self.redirect('/index')
else:
self.redirect('/login')
settings = {
'static_path':'static',
'static_url_prefix':'/sss/',
'template_path':'templates',
} application = tornado.web.Application([
(r"/login", LoginHandler),
(r"/index", IndexHandler),
],**settings) if __name__ == "__main__":
application.listen()
tornado.ioloop.IOLoop.instance().start()
main.py
2)基于redis的session
class RedisSession(object): def __init__(self,handler):
# 获取用户cookies,如果有,不操作,否则给用户生成随机字符串
# - 写给用户
# - 保存在session
nid = handler.get_cookie('session_id')
if nid:
if nid in Session.container:
pass
else:
nid = str(uuid.uuid4())
# Session.container[nid] = {}
# 连接redis写值
else:
nid = str(uuid.uuid4())
# Session.container[nid] = {}
# 连接redis写值
handler.set_cookie('session_id',nid,max_age=) # max_age= 超时时间
# nid 当前访问用户的随机字符串+
self.nid = nid
# 封装了所有用户请求信息
self.handler = handler def __setitem__(self,key,value):
# Session.container[self.nid][key] = value
pass
def __getitem__(self,item):
# return Session.container[self.nid].get(item)
pass
def __delitem__(self, key):
# del Session.container[self.nid][key]
pass
RedisSession
3)设置配置文件,选择使用哪种session
新建配置文件文件
session_key = "RedisSession"
config.py
通过getattr方法找到config文件内容
import config
class BaseHandler(object):
def initialize(self):
import session
cls = getattr(session,config.session_key)
self.session = cls(self)
super(BaseHandler,self).initialize()
BaseHandler
4)补充,根据算法,计算选择哪台机器,可设置机器的权重来分配机器的任务量
#__author: Administrator
#date: //
import sys
import math
from bisect import bisect if sys.version_info >= (, ):
import hashlib md5_constructor = hashlib.md5
else:
import md5 md5_constructor = md5.new class HashRing(object):
"""一致性哈希""" def __init__(self, nodes):
'''初始化
nodes : 初始化的节点,其中包含节点已经节点对应的权重
默认每一个节点有32个虚拟节点
对于权重,通过多创建虚拟节点来实现
如:nodes = [
{'host':'127.0.0.1:8000','weight':},
{'host':'127.0.0.1:8001','weight':},
{'host':'127.0.0.1:8002','weight':},
]
''' self.ring = dict()
self._sorted_keys = [] self.total_weight = self.__generate_circle(nodes) def __generate_circle(self, nodes):
for node_info in nodes:
self.total_weight += node_info.get('weight', ) for node_info in nodes:
weight = node_info.get('weight', )
node = node_info.get('host', None) virtual_node_count = math.floor(( * len(nodes) * weight) / self.total_weight)
for i in range(, int(virtual_node_count)):
key = self.gen_key_thirty_two('%s-%s' % (node, i))
if self._sorted_keys.__contains__(key):
raise Exception('该节点已经存在.')
self.ring[key] = node
self._sorted_keys.append(key) def add_node(self, node):
''' 新建节点
node : 要添加的节点,格式为:{'host':'127.0.0.1:8002','weight':},其中第一个元素表示节点,第二个元素表示该节点的权重。
'''
node = node.get('host', None)
if not node:
raise Exception('节点的地址不能为空.') weight = node.get('weight', ) self.total_weight += weight
nodes_count = len(self._sorted_keys) + virtual_node_count = math.floor(( * nodes_count * weight) / self.total_weight)
for i in range(, int(virtual_node_count)):
key = self.gen_key_thirty_two('%s-%s' % (node, i))
if self._sorted_keys.__contains__(key):
raise Exception('该节点已经存在.')
self.ring[key] = node
self._sorted_keys.append(key) def remove_node(self, node):
''' 移除节点
node : 要移除的节点 '127.0.0.1:8000'
'''
for key, value in self.ring.items():
if value == node:
del self.ring[key]
self._sorted_keys.remove(key) def get_node(self, string_key):
'''获取 string_key 所在的节点'''
pos = self.get_node_pos(string_key)
if pos is None:
return None
return self.ring[self._sorted_keys[pos]].split(':') def get_node_pos(self, string_key):
'''获取 string_key 所在的节点的索引'''
if not self.ring:
return None key = self.gen_key_thirty_two(string_key)
nodes = self._sorted_keys
pos = bisect(nodes, key)
return pos def gen_key_thirty_two(self, key): m = md5_constructor()
m.update(bytes(key,encoding='utf-8'))
return int(m.hexdigest(), ) def gen_key_sixteen(self, key): b_key = self.__hash_digest(key)
return self.__hash_val(b_key, lambda x: x) def __hash_val(self, b_key, entry_fn):
return (
(b_key[entry_fn()] << ) | (b_key[entry_fn()] << ) | (b_key[entry_fn()] << ) | b_key[entry_fn()]) def __hash_digest(self, key):
m = md5_constructor()
m.update(bytes(key, encoding='utf-8'))
return map(ord, m.digest()) nodes = [
{'host':'127.0.0.1:8000','weight':},
{'host':'127.0.0.1:8001','weight':},
{'host':'127.0.0.1:8002','weight':},
] ring = HashRing(nodes)
result = ring.get_node('asdfasdfasdf')
print(result)
四、form验证,生成html标签
1)自定义版本form验证
import tornado.web
import re
class StringField:
def __init__(self,name):
self.rex = "^\w+$"
self.name = name
self.value = ''
self.error = "" def __str__(self):
return "<input type='text' name='%s' value='%s' />" %(self.name,self.value,)
class EmailField:
def __init__(self,name):
self.rex = "^\w+@.*$"
self.name = name
self.value = ''
self.error = ""
def __str__(self):
return "<input type='text' name='%s' value='%s' />" %(self.name,self.value,) class LoginForm:
def __init__(self):
self.user = StringField(name='user')
self.email = EmailField(name='email') def is_valid(self,handler):
value_dict = {}
flag = True
for k,v in self.__dict__.items():
inp = handler.get_argument(k)
# : k=user, inp='asdf' v ="\w+" => StringField(name='user')
# : k=email, inp='asdfasdf' v ="^\w+@.*$" => EmailField(name='email')
rex = re.match(v.rex,inp)
v.value = inp
if rex:
value_dict[k] = inp
else:
v.error = '%s 错误了..' %k
flag = False
return flag,value_dict class LoginHandler(tornado.web.RequestHandler): def get(self, *args, **kwargs):
obj = LoginForm()
self.render('login.html',**{'obj': obj}) def post(self, *args, **kwargs):
obj = LoginForm()
valid,value_dict = obj.is_valid(self)
print(valid,value_dict)
if valid:
print(value_dict)
else:
return self.render('login.html',**{'obj': obj}) settings = {
'static_path': 'static',
'static_url_prefix': '/sss/',
'template_path':'templates',
}
application = tornado.web.Application([
(r"/login", LoginHandler),
],**settings) if __name__ == "__main__":
application.listen()
tornado.ioloop.IOLoop.instance().start()
五、pymysql连接数据库测试登录版本的tornado
#!/usr/bin/env python
#-*-coding: utf- -*-
import tornado.ioloop
import tornado.web
import pymysql class MainHandler(tornado.web.RequestHandler):
def get(self): #get 和 post的区别,get,url中传输数据
self.render("login.html") def post(self, *args, **kwargs): # 获取用户提交的数据a
username = self.get_argument('username', None) # 获取数据,通过,get_argument
pwd = self.get_argument('pwd', None) # 创建数据库连接
conn = pymysql.connect(host='127.0.0.1', port=, user='root', passwd='', db='db1')
cursor = conn.cursor()
# temp = "select name from userinfo where name='%s' and password = '%s'" % (username, pwd) # 不安全
# print(temp)
effect_row = cursor.execute("select name from userinfo where name= %s and password = %s ", (username, pwd,)) #安全些
result = cursor.fetchone()
conn.commit()
cursor.close()
conn.close()
if result:
self.write('登录成功')
else:
self.write('登录失败') settings = {
"template_path":"template", # 模板路径
'static_path': 'static', # 静态文件的处理,即对css文件的处理
'static_url_prefix': '/static/', # 静态文件的前缀
} # 路由映射,路由系统
application = tornado.web.Application([
(r"/login", MainHandler), # ==》login.html
],**settings) if __name__ == "__main__":
application.listen()
tornado.ioloop.IOLoop.instance().start()
2. login.html 文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/login" method="post">
<input type="text" name="username" placeholder="用户" />
<input type="text" name="pwd" placeholder="密码" />
<input type="submit" />
</form>
</body>
</html>
login.html
三、在tornado中定义模板路径
在模板中默认提供了一些函数、字段、类以供模板使用:
escape
:tornado.escape.xhtml_escape
的別名xhtml_escape
:tornado.escape.xhtml_escape
的別名url_escape
:tornado.escape.url_escape
的別名json_encode
:tornado.escape.json_encode
的別名squeeze
:tornado.escape.squeeze
的別名linkify
:tornado.escape.linkify
的別名datetime
: Python 的datetime
模组handler
: 当前的RequestHandler
对象request
:handler.request
的別名current_user
:handler.current_user
的別名locale
:handler.locale
的別名_
:handler.locale.translate
的別名static_url
: forhandler.static_url
的別名xsrf_form_html
:handler.xsrf_form_html
的別名
Tornado默认提供的这些功能其实本质上就是 UIMethod 和 UIModule,我们也可以自定义从而实现类似于Django的simple_tag的功能:
1、定义
def tab(self):
return 'UIMethod'
uimethods.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from tornado.web import UIModule
from tornado import escape class custom(UIModule): def render(self, *args, **kwargs):
return escape.xhtml_escape('<h1>user</h1>')
#return escape.xhtml_escape('<h1>user</h1>')
uimodules.py
2、注册
#!/usr/bin/env python
# -*- coding:utf-8 -*- import tornado.ioloop
import tornado.web
from tornado.escape import linkify
import uimodules as md
import uimethods as mt 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,
'ui_modules': md,
} application = tornado.web.Application([
(r"/index", MainHandler),
], **settings) if __name__ == "__main__":
application.listen(8009)
tornado.ioloop.IOLoop.instance().start()
main.py
3、使用
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<link href="{{static_url("commons.css")}}" rel="stylesheet" />
</head>
<body>
<h1>hello</h1>
</body>
</html>
index.html
四、关于tornado的cookie的认识
cookie值即是用户登录系统后所有产生的cookie值,保留这种用户的客户端,再次登录只需要验证cookie值,就可登录成功
1、定义一个首页
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>首页</h1>
</body>
</html>
index.html
2、定义登录页
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/login" method="post">
<input type="text" name="username" />
<input type="password" name="password" />
<input type="submit" value="登录" />
<span style="color: red">{{status_text}}</span>
</form>
</body>
</html>
login.html
3、定义登录后才见到的页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<a href="/logout">退出</a>
<h1>银行卡余额1000</h1>
</body>
</html>
manager.html
4、主程序。逻辑关系的呈现
#!/usr/bin/env python
#-*-coding: utf8-*- # 项目一,关于cookis的认识
# viems文件夹
# index.html 主页
# login.html 登录页
# manager.html 登录能看的页
# __init__.py
# runmain.py import tornado.ioloop
import tornado.web # 定义首页
class IndexHandler(tornado.web.RequestHandler):
def get(self,*args,**kwargs):
self.render('index.html',) # 定义需要登录才能看到的页面,即需要有cookie
class ManagerHandler(tornado.web.RequestHandler):
def get(self,*args,**kwargs):
co = self.get_cookie('auth')
if co == '':
self.render('manager.html',)
else:
self.redirect("/login")
# 定义登录后出现的退出程序
class LogoutHandler(tornado.web.RequestHandler):
def get(self, *args, **kwargs):
self.get_cookie('auth','')
self.render('/login' ) # 定义登录页,如果成功,则产生cookie
class LoginHandler(tornado.web.RequestHandler):
def get(self,*args,**kwargs):
self.render('login.html',status_text="") def post(self, *args, **kwargs):
username = self.get_argument('username',None)
pwd = self.get_argument('password',None)
if username == 'user' and pwd == "sb":
self.set_cookie('auth','')
self.redirect('/manager')
else:
self.render('login.html',status_text="登录失败") settings = {
'template_path':'viems',
} application = tornado.web.Application([
(r"/index", IndexHandler),
(r"/login", LoginHandler),
(r"/manager", ManagerHandler),
(r"/logout",LogoutHandler)
], **settings) if __name__ == "__main__":
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()
runmain.py
运行程序,检验其逻辑关系,各个页面。127.0.0.1:8888/index ,127.0.0.1:8888/login,各个cookie值
5、补充cookie保存的时间,增加cookie值带的用户名
class LoginHandler(tornado.web.RequestHandler):
def get(self,*args,**kwargs):
self.render('login.html',status_text="") def post(self, *args, **kwargs):
username = self.get_argument('username',None)
pwd = self.get_argument('password',None)
check = self.get_argument('auto',None)
if username == 'user' and pwd == "sb":
if check:
self.set_cookie('username',username,expires_days=7)
self.set_cookie('auth','',expires_days=7)
else:
r = time.time() + 100
self.set_cookie('auth','',expires=r)
self.set_cookie('username', username, expires=r)
self.redirect('/manager')
else:
self.render('login.html',status_text="登录失败")
time()_cookies.py
<body>
<form action="/login" method="post">
<input type="text" name="username" />
<input type="password" name="password" />
<input type="checkbox" name="auto" value="1" />7天免登录
<input type="submit" value="登录" /> <span style="color: red">{{status_text}}</span>
</form>
</body>
time()_cookie.html
Python之tornado的更多相关文章
- 【Python】使用python的tornado配合html页面示例
背景:java写的非标加密算法,测试时执行java工程进行解密测试,很不方便. 目的:想写个web页面,使得任何测试人员都可以在输入加密串时得到解密后字段,方便日志查询及字段核对.(额,算法部分就不写 ...
- RHEL6安装python包tornado
RHEL6安装python包tornado tornado是使用Python开发的全栈式(full-stack)Web框架和异步网络库,最早由Friendfeed开发.通过使用非阻塞IO,Tornad ...
- Centos搭建Python+Nginx+Tornado+Mysql环境[转载]
Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like 协议下发行.由俄罗斯的程序设计师Igor Sysoev所开发,供俄国大型的入 ...
- python 之tornado 入门
#!/usr/bin/env python # -*- coding:utf-8 -*- # --------------------------------------- # email : gen ...
- centos上发布部署python的tornado网站项目完整流程
先说下大体上的做法,开发环境上要新弄一个 virtualenv的环境,在这个里面放你的开发调试,当然这个其实也不是必须的,但是这样会方便管理一些. 再在centos上也弄一个 virtualenv虚拟 ...
- Python的Tornado框架的异步任务与AsyncHTTPClient
转载自http://www.php.cn/python-tutorials-284773.html 高性能服务器TornadoPython的web框架名目繁多,各有千秋.正如光荣属于希腊,伟大属于罗马 ...
- python中tornado的第一个例子
1 先安装tornado pip install tornado 2 新建tor.py 记住不能建立 tornado.py 这样的名字 不然会报错 ImportError: No module n ...
- python 之Tornado
一.Tomado Tornado 是 FriendFeed 使用的可扩展的非阻塞式 web 服务器及其相关工具的开源版本.这个 Web 框架看起来有些像web.py 或者 Google 的 webap ...
- Python之tornado框架原理
Python web框架 1.简单概念 tornado socket.逻辑处理 Django flask 逻辑处理 第三方处理模块(包含了socket) jinja2模块 Models 数据库处理 V ...
随机推荐
- pta7-18奥运排行榜(模拟)
题目链接:https://pintia.cn/problem-sets/1101307589335527424/problems/1101314114867245056 题意:给n个国家,以及每个国家 ...
- WAS 添加数据源
一.创建安全性别名认证 1.资源-全局安全性-JAVA认证和授权服务-J2C认证数据 2.新建 3.输入别名,这里后面加IP末尾.输入用户名.密码. 4.点击确定.保存. 二.创建数据源连接配置 1. ...
- CentOS 几种重启方式的区别
Linux centos重启命令: 1.reboot 普通重启 2.shutdown -r now 立刻重启(root用户使用) 3.shutdown -r 10 过10分钟自动重启(root用户 ...
- PAT1131(dfs)
In the big cities, the subway systems always look so complex to the visitors. To give you some sense ...
- Unity3D游戏贪吃蛇大作战源码休闲益智手机小游戏完整项目
<贪吃蛇大作战>一款休闲竞技游戏,不仅比拼手速,更考验玩家的策略. 视频演示: http://player.youku.com/player.php/sid/XMzc5ODA2Njg1Ng ...
- TZOJ 1513 Farm Tour(最小费用最大流)
描述 When FJ's friends visit him on the farm, he likes to show them around. His farm comprises N (1 &l ...
- java中Date无法获取数据库时分秒的问题
数据库使用的字段是timestamp(6),在数据库看的时候明明时分秒是有的,然而通过rs.getDate()获取出来的时候时分秒就没有了,查了一下资料终于解决了,这里有一个重要的知识点,java ...
- 服务器webapi集成极光推送学习笔记
一路坎坷,坑死你!!!入坑需做好心理准备. 第一天: 其文档支持不给力,和微信的文档支持比起来能气死你,刚开始弄,看了一大堆东西,找不到头绪从哪里开始弄.只好找了一些文档,先了解了其基本原理,参考文章 ...
- 9.11 h5日记
9.11 超链接标签<a></a>十分特殊改a标签内容的字体颜色,必须是直接给a 设置,给它的父级标签设置是不可行的. PS:什么是属性继承,即父级标签设置的样式后 ...
- Django 模板语言 路由 视图
. 模板语言(字符串替换) . 母版和继承 . 什么时候用母版? html页面有重复的代码,把它们提取出来放到一个单独的html文件. (比如:导航条和左侧菜单) . 子页面如何使用母版? {% ex ...