简单介绍Python的轻便web框架Bottle


Posted in Python onApril 08, 2015

基本映射

映射使用在根据不同URLs请求来产生相对应的返回内容.Bottle使用route() 修饰器来实现映射.

from bottle import route, run@route('/hello')def hello():
  return "Hello World!"run() # This starts the HTTP server

运行这个程序,访问http://localhost:8080/hello将会在浏览器里看到 "Hello World!".
GET, POST, HEAD, ...

这个映射装饰器有可选的关键字method默认是method='GET'. 还有可能是POST,PUT,DELETE,HEAD或者监听其他的HTTP请求方法.

from bottle import route, request@route('/form/submit', method='POST')def form_submit():
  form_data = request.POST
  do_something(form_data)
  return "Done"

动态映射

你可以提取URL的部分来建立动态变量名的映射.
 

@route('/hello/:name')def hello(name):
  return "Hello %s!" % name

默认情况下, 一个:placeholder会一直匹配到下一个斜线.需要修改的话,可以把正则字符加入到#s之间:

@route('/get_object/:id#[0-9]+#')def get(id):
  return "Object ID: %d" % int(id)

或者使用完整的正则匹配组来实现:

@route('/get_object/(?P<id>[0-9]+)')def get(id):
  return "Object ID: %d" % int(id)

正如你看到的,URL参数仍然是字符串, 即使你正则里面是数字.你必须显式的进行类型强制转换.
@validate() 装饰器

Bottle 提供一个方便的装饰器validate() 来校验多个参数.它可以通过关键字和过滤器来对每一个URL参数进行处理然后返回请求.

from bottle import route, validate# /test/validate/1/2.3/4,5,6,7@route('/test/validate/:i/:f/:csv')@validate(i=int, f=float, csv=lambda x: map(int, x.split(',')))def validate_test(i, f, csv):
  return "Int: %d, Float:%f, List:%s" % (i, f, repr(csv))

你可能需要在校验参数失败时抛出ValueError.
返回文件流和JSON

WSGI规范不能处理文件对象或字符串.Bottle自动转换字符串类型为iter对象.下面的例子可以在Bottle下运行, 但是不能运行在纯WSGI环境下.

@route('/get_string')def get_string():
  return "This is not a list of strings, but a single string"@route('/file')def get_file():
  return open('some/file.txt','r')

字典类型也是允许的.会转换成json格式,自动返回Content-Type: application/json.

@route('/api/status')def api_status():
  return {'status':'online', 'servertime':time.time()}

你可以关闭这个特性:bottle.default_app().autojson = False
Cookies

Bottle是把cookie存储在request.COOKIES变量中.新建cookie的方法是response.set_cookie(name, value[, **params]). 它可以接受额外的参数,属于SimpleCookie的有有效参数.

from bottle import responseresponse.set_cookie('key','value', path='/', domain='example.com', secure=True, expires=+500, ...)

设置max-age属性(它不是个有效的Python参数名) 你可以在实例中修改 cookie.SimpleCookie inresponse.COOKIES.
 

from bottle import responseresponse.COOKIES['key'] = 'value'response.COOKIES['key']['max-age'] = 500

模板

Bottle使用自带的小巧的模板.你可以使用调用template(template_name, **template_arguments)并返回结果.
 

@route('/hello/:name')def hello(name):
  return template('hello_template', username=name)

这样就会加载hello_template.tpl,并提取URL:name到变量username,返回请求.

hello_template.tpl大致这样:

<h1>Hello {{username}}</h1><p>How are you?</p>

模板搜索路径

模板是根据bottle.TEMPLATE_PATH列表变量去搜索.默认路径包含['./%s.tpl', './views/%s.tpl'].
模板缓存

模板在编译后在内存中缓存.修改模板不会更新缓存,直到你清除缓存.调用bottle.TEMPLATES.clear().
模板语法

模板语法是围绕Python很薄的一层.主要目的就是确保正确的缩进块.下面是一些模板语法的列子:

  •     %...Python代码开始.不必处理缩进问题.Bottle会为你做这些.
  •     %end关闭一些语句%if ...,%for ...或者其他.关闭块是必须的.
  •     {{...}}打印出Python语句的结果.
  •     %include template_name optional_arguments包括其他模板.
  •     每一行返回为文本.

Example:

%header = 'Test Template'
%items = [1,2,3,'fly']
%include http_header title=header, use_js=['jquery.js', 'default.js']<h1>{{header.title()}}</h1><ul>%for item in items: <li>
  %if isinstance(item, int):
   Zahl: {{item}}
  %else:
   %try:
    Other type: ({{type(item).__name__}}) {{repr(item)}}
   %except:
    Error: Item has no string representation.
   %end try-block (yes, you may add comments here)
  %end  </li>
 %end</ul>%include http_footer

Key/Value数据库

Bottle(>0.4.6)通过bottle.db模块变量提供一个key/value数据库.你可以使用key或者属性来来存取一个数据库对象.调用 bottle.db.bucket_name.key_name和bottle.db[bucket_name][key_name].

只要确保使用正确的名字就可以使用,而不管他们是否已经存在.

存储的对象类似dict字典, keys和values必须是字符串.不支持 items() and values()这些方法.找不到将会抛出KeyError.
持久化

对于请求,所有变化都是缓存在本地内存池中. 在请求结束时,自动保存已修改部分,以便下一次请求返回更新的值.数据存储在bottle.DB_PATH文件里.要确保文件能访问此文件.
Race conditions

一般来说不需要考虑锁问题,但是在多线程或者交叉环境里仍是个问题.你可以调用 bottle.db.save()或者botle.db.bucket_name.save()去刷新缓存,但是没有办法检测到其他环境对数据库的操作,直到调用bottle.db.save()或者离开当前请求.
Example
 

from bottle import route, db@route('/db/counter')def db_counter():
  if 'hits' not in db.counter:
    db.counter.hits = 0
  db['counter']['hits'] += 1
  return "Total hits: %d!" % db.counter.hits

使用WSGI和中间件

bottle.default_app()返回一个WSGI应用.如果喜欢WSGI中间件模块的话,你只需要声明bottle.run()去包装应用,而不是使用默认的.
 

from bottle import default_app, runapp = default_app()newapp = YourMiddleware(app)run(app=newapp)

默认default_app()工作

Bottle创建一个bottle.Bottle()对象和装饰器,调用bottle.run()运行. bottle.default_app()是默认.当然你可以创建自己的bottle.Bottle()实例.

from bottle import Bottle, runmybottle = Bottle()@mybottle.route('/')def index():
 return 'default_app'run(app=mybottle)

发布

Bottle默认使用wsgiref.SimpleServer发布.这个默认单线程服务器是用来早期开发和测试,但是后期可能会成为性能瓶颈.

有三种方法可以去修改:

  1.     使用多线程的适配器
  2.     负载多个Bottle实例应用
  3.     或者两者

多线程服务器

最简单的方法是安装一个多线程和WSGI规范的HTTP服务器比如Paste, flup, cherrypy or fapws3并使用相应的适配器.
 
from bottle import PasteServer, FlupServer, FapwsServer, CherryPyServerbottle.run(server=PasteServer) # Example

如果缺少你喜欢的服务器和适配器,你可以手动修改HTTP服务器并设置bottle.default_app()来访问你的WSGI应用.

def run_custom_paste_server(self, host, port):
  myapp = bottle.default_app()
  from paste import httpserver
  httpserver.serve(myapp, host=host, port=port)

多服务器进程

一个Python程序只能使用一次一个CPU,即使有更多的CPU.关键是要利用CPU资源来负载平衡多个独立的Python程序.

单实例Bottle应用,你可以通过不同的端口来启动(localhost:8080, 8081, 8082, ...).高性能负载作为反向代理和远期每一个随机瓶进程的新要求,平衡器的行为,传播所有可用的支持与服务器实例的负载.这样,您就可以使用所有的CPU核心,甚至分散在不同的物理服

Python 相关文章推荐
python高并发异步服务器核心库forkcore使用方法
Nov 26 Python
python登录豆瓣并发帖的方法
Jul 08 Python
Python中的super()方法使用简介
Aug 14 Python
详解python上传文件和字符到PHP服务器
Nov 24 Python
Python实现正弦信号的时域波形和频谱图示例【基于matplotlib】
May 04 Python
win10下python3.5.2和tensorflow安装环境搭建教程
Sep 19 Python
python 读取文件并把矩阵转成numpy的两种方法
Feb 12 Python
Python 硬币兑换问题
Jul 29 Python
Python远程开发环境部署与调试过程图解
Dec 09 Python
Django+boostrap 美化admin后台的操作
Mar 11 Python
pandas求平均数和中位数的方法实例
Aug 04 Python
python入门学习关于for else的特殊特性讲解
Nov 20 Python
常见的在Python中实现单例模式的三种方法
Apr 08 #Python
分析Python的Django框架的运行方式及处理流程
Apr 08 #Python
给Python的Django框架下搭建的BLOG添加RSS功能的教程
Apr 08 #Python
在Python中使用NLTK库实现对词干的提取的教程
Apr 08 #Python
使用Python操作Elasticsearch数据索引的教程
Apr 08 #Python
用Python实现协同过滤的教程
Apr 08 #Python
在Python中调用ggplot的三种方法
Apr 08 #Python
You might like
php+mysql写的简单留言本实例代码
2008/07/25 PHP
深入PHP购物车模块功能分析(函数讲解,附源码)
2013/06/25 PHP
PHP模拟登陆163邮箱发邮件及获取通讯录列表的方法
2015/03/07 PHP
PHP 将dataurl转成图片image方法总结
2016/10/14 PHP
PHP实现表单提交数据的验证处理功能【防SQL注入和XSS攻击等】
2017/07/21 PHP
php生成微信红包数组的方法
2019/09/05 PHP
jQuery AJAX回调函数this指向问题
2010/02/08 Javascript
关于innerHTML后丢失动态绑定的EVENT问题解决方法
2013/05/19 Javascript
javascript实现文字图片上下滚动的具体实例
2013/06/28 Javascript
Nodejs进程管理模块forever详解
2014/06/01 NodeJs
用svg制作富有动态的tooltip
2015/07/17 Javascript
JavaScript重载函数实例剖析
2016/05/13 Javascript
jQuery插件实现可输入和自动匹配的下拉框
2016/10/24 Javascript
vuex实现简易计数器
2016/10/27 Javascript
完美解决jQuery fancybox ie 无法显示关闭按钮的问题
2016/11/29 Javascript
Servlet实现文件上传,可多文件上传示例
2016/12/05 Javascript
jQuery基于事件控制实现点击显示内容下拉效果
2017/03/07 Javascript
详解用node-images 打造简易图片服务器
2017/05/08 Javascript
JavaScript创建对象的七种方式全面总结
2017/08/21 Javascript
Vue 开发必须知道的36个技巧(小结)
2019/10/09 Javascript
ES6 class类链式继承,实例化及react super(props)原理详解
2020/02/15 Javascript
vue+element_ui上传文件,并传递额外参数操作
2020/12/05 Vue.js
ES2020让代码更优美的运算符 (?.) (??)
2021/01/04 Javascript
[09:47]2018DOTA2亚洲邀请赛4.5SOLO赛 No[o]ne vs Sumail
2018/04/06 DOTA
跟老齐学Python之数据类型总结
2014/09/24 Python
Python实现多线程抓取妹子图
2015/08/08 Python
对python requests的content和text方法的区别详解
2018/10/11 Python
浅谈Python中的bs4基础
2018/10/21 Python
python matplotlib库直方图绘制详解
2019/08/10 Python
一篇文章弄懂Python中的可迭代对象、迭代器和生成器
2019/08/12 Python
Python格式化输出--%s,%d,%f的代码解析
2020/04/29 Python
Django生成数据库及添加用户报错解决方案
2020/10/09 Python
python+requests实现接口测试的完整步骤
2020/10/27 Python
2015年幼儿园教育教学工作总结
2015/05/25 职场文书
2016年“9.22”世界无车日活动小结
2016/04/05 职场文书
SQL Server查询某个字段在哪些表中存在
2022/03/03 SQL Server