简单介绍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实现zencart产品数据导入到magento(python导入数据)
Apr 03 Python
Python三级目录展示的实现方法
Sep 28 Python
用pickle存储Python的原生对象方法
Apr 28 Python
node.js获取参数的常用方法(总结)
May 29 Python
Python实现将文本生成二维码的方法示例
Jul 18 Python
python pandas库中DataFrame对行和列的操作实例讲解
Jun 09 Python
Python通过paramiko远程下载Linux服务器上的文件实例
Dec 27 Python
对python中list的拷贝与numpy的array的拷贝详解
Jan 29 Python
Scrapy框架实现的登录网站操作示例
Feb 06 Python
python 成功引入包但无法正常调用的解决
Mar 09 Python
python属于哪种语言
Aug 16 Python
工程师必须了解的LRU缓存淘汰算法以及python实现过程
Oct 15 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 cdata 处理(详细介绍)
2013/07/05 PHP
PHP的魔术常量__METHOD__简介
2014/07/08 PHP
利用javascript查看html源文件
2006/11/08 Javascript
用倒置滤镜把div倒置,再把table倒置。
2007/07/31 Javascript
JavaScript 页面编码与浏览器类型判断代码
2010/06/03 Javascript
struts2+jquery+json实现异步加载数据(自写)
2013/06/24 Javascript
jQuery随便控制任意div隐藏的方法
2013/06/28 Javascript
JS实现随机乱撞彩色圆球特效的方法
2015/05/05 Javascript
浅谈JavaScript的push(),pop(),concat()方法
2016/06/03 Javascript
JavaScript实现图片懒加载(Lazyload)
2016/11/28 Javascript
JavaScript浏览器对象模型BOM(BrowserObjectModel)实例详解
2016/11/29 Javascript
微信小程序-拍照或选择图片并上传文件
2017/01/06 Javascript
jQuery插件FusionWidgets实现的Cylinder图效果示例【附demo源码】
2017/03/23 jQuery
详解Angular2表单-模板驱动的表单(Template-Driven Forms)
2017/08/04 Javascript
webpack5 联邦模块介绍详解
2020/07/08 Javascript
vue3.0搭配.net core实现文件上传组件
2020/10/29 Javascript
[00:17]DOTA2荣耀之路5:It’s a disastah!
2018/05/28 DOTA
[36:09]Secret vs VG 2019国际邀请赛淘汰赛 败者组 BO3 第一场 8.24
2019/09/10 DOTA
python实现的登陆Discuz!论坛通用代码分享
2014/07/11 Python
Python中bisect的用法
2014/09/23 Python
python有证书的加密解密实现方法
2014/11/19 Python
Python实现简单拆分PDF文件的方法
2015/07/30 Python
win与linux系统中python requests 安装
2016/12/04 Python
Python实现的朴素贝叶斯分类器示例
2018/01/06 Python
python selenium 获取标签的属性值、内容、状态方法
2018/06/22 Python
基于python二叉树的构造和打印例子
2019/08/09 Python
Python的历史与优缺点整理
2020/05/26 Python
Pandas之缺失数据的实现
2021/01/06 Python
HTML5之SVG 2D入门2—图形绘制(基本形状)介绍及使用
2013/01/30 HTML / CSS
网络技术支持面试题
2013/04/22 面试题
师范院校学生自荐信范文
2013/12/27 职场文书
公职人员索取回扣检举信
2014/04/04 职场文书
机械电子工程专业自荐书
2014/06/10 职场文书
2015年端午节国旗下演讲稿
2015/03/19 职场文书
幼儿园开学家长寄语(2015秋季)
2015/05/27 职场文书
Python使用OpenCV实现虚拟缩放效果
2022/02/28 Python