目录

  • 1 前言
  • 2 SWGI(Web Server Gateway Interface)
  • 3 特色与优势
  • 4 Hello, World!
  • 5 不同URL调用不同函数
  • 6 带有参数的URL
  • 7 处理表单
  • 8 跟踪终端用户状态
  • 9 支持静态内容(javascript,css,images)
  • 10 支持REST(Representational State Transfer)
  • 11 支持Ajax
  • 12 支持数据存储
  • 13 组织代码
  • 14 后记
  • 15 参考

1 前言

CherryPy 是一个极简主义风格的 Pythonic Web框架.

前段时间使用了下,用于接收VBA程序的HTTP(Hypertext Transfer Protocol)请求,这里做个学习笔记。

2 SWGI(Web Server Gateway Interface)

早期Python应用程序通常是为 CGIFastCGImod_python 中的一个而设计,甚至是为特定Web服务器的自定义的API接口而设计.

SWGI 是Python专用的 Web服务器 和 Web应用程序或框架 之间的一种简单而通用的接口协议,是Python web程序开发的标准,具体查看 PEP 0333 内容(Python3.x 查看PEP 3333). WSGI是基于现存的CGI标准而设计.

常用的Python Web框架(兼容SWGI)有(http://en.wikipedia.org/wiki/Category:Python_web_application_frameworks):

  • BlueBream
  • CherryPy
  • Django
  • Flask
  • Grok
  • Nagare
  • Nevow
  • Pyjamas
  • Pylons
  • Pyramid
  • Quixote
  • Spyce
  • TACTIC
  • Tornado
  • TurboGears
  • TwistedWeb
  • Webware
  • web.py
  • web2py
  • Zope

类似的,在其他语言进行Web开发也有相应的接口协议,如:

  • Rack – Ruby web server interface
  • PSGI – Perl Web Server Gateway Interface
  • SCGI – Simple Common Gateway Interface
  • JSGI – JavaScript web server gateway interface

3 特色与优势

  • 可靠、兼容HTTP/1.1、支持WSGI线程池(thread-pooled)的Web服务器
  • 同时运行多个HTTP服务器(通过不同端口)
  • 为开发和部署提供强大的配置文件系统
  • 灵活的插件系统
  • 内置工具包括缓存、编码、会话、授权和静态内容等
  • 可定制
  • 内置性能分析和测试功能
  • 可以运行在Python 2.5+, 3.1+, PyPy, Jython和Android等环境

4 Hello, World!

CherryPy 在设计风格方面,尽量的保持Pythonic,具有鲜明的Python风格;既可以作为一个Web框架,也可以作为一个普通模块使用。

一个简单的范例:

import cherrypy
class HelloWorld(object):def index(self):return "Hello World!"index.exposed = True
cherrypy.quickstart(HelloWorld())

或者:

import cherrypy
class HelloWorld(object):@cherrypy.exposedef index(self):return "Hello World!"
cherrypy.quickstart(HelloWorld())

5 不同URL调用不同函数

import random
import string
import cherrypy
class StringGenerator(object):@cherrypy.exposedef index(self):return "Hello world!"@cherrypy.exposedef generate(self):return ''.join(random.sample(string.hexdigits, 8))
if __name__ == '__main__':cherrypy.quickstart(StringGenerator())

启动服务器后,函数 generate 对应处理的URL是 http://localhost:8080/generate ,对于URL:

  • http:// : 指明使用的协议是HTTP协议
  • localhost:8080 : 这是服务器地址
  • /generate: 这是URL的path

6 带有参数的URL

import random
import string
import cherrypy
class StringGenerator(object):@cherrypy.exposedef index(self):return "Hello world!"@cherrypy.exposedef generate(self, length=8, prefix=""):return preix + ''.join(random.sample(string.hexdigits, int(length)))
if __name__ == '__main__':cherrypy.quickstart(StringGenerator())

对应的URL是 http://localhost:8080/generate?length=16&prefix=Return, 在 ? 之后的叫 query_string, 会被解析成 (key,value) 形式,用 & 分隔。

7 处理表单

import random
import string
import cherrypy
class StringGenerator(object):@cherrypy.exposedef index(self):return """<html><head></head><body><form method="get" action="generate"><input type="text" value="8" name="length" /><button type="submit">Give it now!</button></form></body></html>"""@cherrypy.exposedef generate(self, length=8):return ''.join(random.sample(string.hexdigits, int(length)))
if __name__ == '__main__':cherrypy.quickstart(StringGenerator())

会将表单 GET 动作会被解析为 query-string (key, value)对 ,然后调用对应的函数。

8 跟踪终端用户状态

import random
import string
import cherrypy
class StringGenerator(object):@cherrypy.exposedef index(self):return """<html><head></head><body><form method="get" action="generate"><input type="text" value="8" name="length" /><button type="submit">Give it now!</button></form></body></html>"""@cherrypy.exposedef generate(self, length=8):some_string = ''.join(random.sample(string.hexdigits, int(length)))cherrypy.session['mystring'] = some_stringreturn some_string@cherrypy.exposedef display(self):return cherrypy.session['mystring']
if __name__ == '__main__':conf = {'/': {'tools.sessions.on': True}}cherrypy.quickstart(StringGenerator(), '/', conf)

通过提供 配置文件 激活 会话功能 ,从而跟踪用户状态,对于 cherrypy.quickstart:

  • quickstart(root=None, script_name='', config=None) : Mount the given root, start the builtin server (and engine), then block.

    • root: 用于接受/处理HTTP请求的类的实例
    • script_name: 一个表示挂载点的字符串,应该以 / 开头并不可以以 / 结束
    • config: 一个作为配置文件的dict结构

9 支持静态内容(javascript,css,images)

创建文件 : ./public/css/style.css, 不需要创建 ./static

import os, os.pathimport randomimport stringimport cherrypyclass StringGenerator(object):@cherrypy.exposedef index(self):return """<html><head><link href="http://lesliezhu.github.com/static/css/style.css" rel="stylesheet"></head><body><form method="get" action="generate"><input type="text" value="8" name="length" /><button type="submit">Give it now!</button></form></body></html>"""@cherrypy.exposedef generate(self, length=8):some_string = ''.join(random.sample(string.hexdigits, int(length)))cherrypy.session['mystring'] = some_stringreturn some_string@cherrypy.exposedef display(self):return cherrypy.session['mystring']if __name__ == '__main__':conf = {'/': {'tools.sessions.on': True,'tools.staticdir.root': os.path.abspath(os.getcwd())},'/static': {'tools.staticdir.on': True,'tools.staticdir.dir': './public'}}cherrypy.quickstart(StringGenerator(), '/', conf)

对于静态内容,处于安全考虑,进行了一个映射,将 /static 变成了 /public ,这样用户就只能访问web服务器访问的静态内容,无法访问其他文件,因为不知道实际的路径。

如果没有设置映射, cherrypy会检查,如:

CherryPy Checker:
tools.staticdir.dir is not set.
section: [/static]
root: '/path/to/cherrypy'
dir: None

10 支持REST(Representational State Transfer)

目前在三种主流的Web服务实现方案中,因为 REST模式 与复杂的 SOAP 和 XML-RPC 相比更加简洁,越来越多的web服务开始采用REST风格设计和实现。

REST是 设计风格 而不是标准。REST通常基于使用HTTP,URI,和XML以及HTML这些现有的广泛流行的协议和标准:

  • 资源是由URI来指定。
  • 对资源的操作包括获取、创建、修改和删除资源,这些操作正好对应HTTP协议提供的 GET 、 POST、 PUT 和 DELETE 方法。
  • 通过操作资源的表现形式来操作资源。
  • 资源的表现形式则是XML或者HTML,取决于读者是机器还是人,是消费web服务的客户软件还是web浏览器。当然也可以是任何其他的格式。

REST 是 含状态传输 ,应该注意区别应用的状态和连接协议的状态。HTTP连接是 无状态 的(也就是不记录每个连接的信息),而REST传输会包含 应用的所有状态 信息,因此可以大幅降低对HTTP连接的 重复请求资源消耗。

举例:

import random
import string
import cherrypy
class StringGeneratorWebService(object):exposed = True@cherrypy.tools.accept(media='text/plain')def GET(self):return cherrypy.session['mystring']def POST(self, length=8):some_string = ''.join(random.sample(string.hexdigits, int(length)))cherrypy.session['mystring'] = some_stringreturn some_stringdef PUT(self, another_string):cherrypy.session['mystring'] = another_stringdef DELETE(self):cherrypy.session.pop('mystring', None)
if __name__ == '__main__':conf = {'/': {'request.dispatch': cherrypy.dispatch.MethodDispatcher(),'tools.sessions.on': True,'tools.response_headers.on': True,'tools.response_headers.headers': [('Content-Type', 'text/plain')],}}cherrypy.quickstart(StringGeneratorWebService(), '/', conf)

一方面,通过 exposed = True 来一次性设置,并且不在是进行 函数匹配 的方式进行工作,在配置里面设置了 cherrypy.dispatch.MethodDispatcher 。

另外,为了测试效果,不再使用浏览器,而是使用 requests 模块:

$ pip install requests
$ python
>>> import requests
>>> s = requests.Session()
>>> r = s.get('http://127.0.0.1:8080/')
>>> r.status_code
500
>>> r = s.post('http://127.0.0.1:8080/')
>>> r.status_code, r.text
(200, u'04A92138')
>>> r = s.get('http://127.0.0.1:8080/')
>>> r.status_code, r.text
(200, u'04A92138')
>>> r = s.get('http://127.0.0.1:8080/', headers={'Accept': 'application/json'})
>>> r.status_code
406
>>> r = s.put('http://127.0.0.1:8080/', params={'another_string': 'hello'})
>>> r = s.get('http://127.0.0.1:8080/')
>>> r.status_code, r.text
(200, u'hello')
>>> r = s.delete('http://127.0.0.1:8080/')
>>> r = s.get('http://127.0.0.1:8080/')
>>> r.status_code
500

11 支持Ajax

近年来,web程序已经不再满足于 提交HTML表单,然后刷新整个页面 的工作方式,而是在客户端程序里面决定需要刷新的部分资源,从而不需要从服务器端刷新 整个页面 ,提高性能,降低消耗。

一个使用 jQuery框架 的例子:

import os, os.path
import random
import string
import cherrypy
class StringGenerator(object):@cherrypy.exposedef index(self):return file('index.html')
class StringGeneratorWebService(object):exposed = True@cherrypy.tools.accept(media='text/plain')def GET(self):return cherrypy.session['mystring']def POST(self, length=8):some_string = ''.join(random.sample(string.hexdigits, int(length)))cherrypy.session['mystring'] = some_stringreturn some_stringdef PUT(self, another_string):cherrypy.session['mystring'] = another_stringdef DELETE(self):cherrypy.session.pop('mystring', None)
if __name__ == '__main__':conf = {'/': {'tools.sessions.on': True,'tools.staticdir.root': os.path.abspath(os.getcwd())},'/generator': {'request.dispatch': cherrypy.dispatch.MethodDispatcher(),'tools.response_headers.on': True,'tools.response_headers.headers': [('Content-Type', 'text/plain')],},'/static': {'tools.staticdir.on': True,'tools.staticdir.dir': './public'}}webapp = StringGenerator()webapp.generator = StringGeneratorWebService()cherrypy.quickstart(webapp, '/', conf)

这里看不出有什么区别,主要是 index.html 里面采用了 ajax :

<!DOCTYPE html>
<html><head><link href="http://lesliezhu.github.com/static/css/style.css" rel="stylesheet"><script src="http://code.jquery.com/jquery-2.0.3.min.js"></script><script type="text/javascript">$(document).ready(function() {$("#generate-string").click(function(e) {$.post("/generator", {"length": $("input[name='length']").val()}).done(function(string) {$("#the-string").show();$("#the-string input").val(string);});e.preventDefault();});$("#replace-string").click(function(e) {$.ajax({type: "PUT",url: "/generator",data: {"another_string": $("#the-string").val()}}).done(function() {alert("Replaced!");});e.preventDefault();});$("#delete-string").click(function(e) {$.ajax({type: "DELETE",url: "/generator"}).done(function() {$("#the-string").hide();});e.preventDefault();});});</script></head><body><input type="text" value="8" name="length" /><button id="generate-string">Give it now!</button><div id="the-string"><input type="text" /><button id="replace-string">Replace</button><button id="delete-string">Delete it</button></div></body>
</html>

通过 ajax ,对于指定的部分资源进行更新,其它元素不更新,这样整个页面就不需要反复刷新。

12 支持数据存储

会话信息 只能保持在内存中,如果要长期保存数据,可选的存储数据库:

  • relational: PostgreSQL, SQLite, MariaDB, Firebird
  • column-oriented: HBase, Cassandra
  • key-store: redis, memcached
  • document oriented: Couchdb, MongoDB
  • graph-oriented: neo4j

一个操作 sqlite关系数据库 的例子:

import os, os.pathimport randomimport sqlite3import stringimport cherrypyDB_STRING = "my.db"class StringGenerator(object):@cherrypy.exposedef index(self):return file('index.html')class StringGeneratorWebService(object):exposed = True@cherrypy.tools.accept(media='text/plain')def GET(self):with sqlite3.connect(DB_STRING) as c:c.execute("SELECT value FROM user_string WHERE session_id=?",[cherrypy.session.id])return c.fetchone()def POST(self, length=8):some_string = ''.join(random.sample(string.hexdigits, int(length)))with sqlite3.connect(DB_STRING) as c:c.execute("INSERT INTO user_string VALUES (?, ?)",[cherrypy.session.id, some_string])return some_stringdef PUT(self, another_string):with sqlite3.connect(DB_STRING) as c:c.execute("UPDATE user_string SET value=? WHERE session_id=?",[another_string, cherrypy.session.id])def DELETE(self):with sqlite3.connect(DB_STRING) as c:c.execute("DELETE FROM user_string WHERE session_id=?",[cherrypy.session.id])def setup_database():"""Create the `user_string` table in the databaseon server startup"""with sqlite3.connect(DB_STRING) as con:con.execute("CREATE TABLE user_string (session_id, value)")def cleanup_database():"""Destroy the `user_string` table from the databaseon server shutdown."""with sqlite3.connect(DB_STRING) as con:con.execute("DROP TABLE user_string")if __name__ == '__main__':conf = {'/': {'tools.sessions.on': True,'tools.staticdir.root': os.path.abspath(os.getcwd())},'/generator': {'request.dispatch': cherrypy.dispatch.MethodDispatcher(),'tools.response_headers.on': True,'tools.response_headers.headers': [('Content-Type', 'text/plain')],},'/static': {'tools.staticdir.on': True,'tools.staticdir.dir': './public'}}cherrypy.engine.subscribe('start', setup_database)cherrypy.engine.subscribe('stop', cleanup_database)webapp = StringGenerator()webapp.generator = StringGeneratorWebService()cherrypy.quickstart(webapp, '/', conf)

这里注册了 setup_database 和 cleanup_database 函数作为启动和退出的初始化、清理工作。

13 组织代码

CherryPy 健壮的架构设计为更好的维护代码、更高的灵活性提供了大量机制,主要由三个机制:

  • dispatchers: 如代码里面的 cherrypy.dispatch
  • tools: 如代码里面的 cherrypy.tools
  • plugins: 如代码里面的 cherrypy.engine

14 后记

对Web开发不熟悉,很多概念都是第一次接触,这个是对 CherryPy 最基础的一个手册文档的学习笔记,继续添加其它学习内容。

15 参考

  • http://www.cherrypy.org/
  • https://github.com/cherrypy/cherrypy
  • https://bitbucket.org/cherrypy/cherrypy/wiki/Home
  • http://en.wikipedia.org/wiki/CherryPy
  • http://tools.ietf.org/html/rfc7231
  • http://en.wikipedia.org/wiki/Web_Server_Gateway_Interface
  • http://legacy.python.org/dev/peps/pep-0333/
  • https://cherrypy.readthedocs.org/en/latest/
  • http://cherrypy.readthedocs.org/en/latest/tutorials.html
  • https://www.digitalocean.com/community/tutorials/how-to-deploy-python-wsgi-applications-using-a-cherrypy-web-server-behind-nginx
  • https://cherrypy.readthedocs.org/en/latest/tutorials.html#tutorials
  • http://en.wikipedia.org/wiki/Session_(computer_science)
  • http://www.ibm.com/developerworks/library/ws-restful/index.html
  • http://zh.wikipedia.org/zh/REST
  • http://jquery.com/

CherryPy: 一个极简主义Python Web框架相关推荐

  1. python web框架介绍对比

    Django Python框架虽然说是百花齐放,但仍然有那么一家是最大的,它就是Django.要说Django是Python框架里最好的,有人同意也有人 坚决反对,但说Django的文档最完善.市场占 ...

  2. python的web框架哪个最好学_2018年要学习的10大Python Web框架

    通过为开发人员提供应用程序开发结构,框架使开发人员的生活更轻松.他们自动执行通用解决方案,缩短开发时间,并允许开发人员更多地关注应用程序逻辑而不是常规元素. 在本文中,我们分享了我们自己的前十大Pyt ...

  3. 很多小伙伴不太了解ORM框架的底层原理,这不,冰河带你10分钟手撸一个极简版ORM框架(赶快收藏吧)

    大家好,我是冰河~~ 最近很多小伙伴对ORM框架的实现很感兴趣,不少读者在冰河的微信上问:冰河,你知道ORM框架是如何实现的吗?比如像MyBatis和Hibernate这种ORM框架,它们是如何实现的 ...

  4. 极简主义_网页设计中功能极简主义的真实性要少得多

    极简主义 Written by Jessica Bennett 由杰西卡·贝内特 ( Jessica Bennett)撰写 介绍 (Introduction) "Less is more&q ...

  5. python web框架对比_Python六大开源框架对比

    Python 是一门动态.面向对象语言.其最初就是作为一门面向对象语言设计的,并且在后期又加入了一些更高级的特性.除了语言本身的设计目的之外,Python标准 库也是值得大家称赞的,Python甚至还 ...

  6. “留白” 与 极简主义

    "留白" 设计,是 极简主义设计 外化后的的重要体现 留白在世界 ------------------------- 1939年9月,以德国 / 意大利 / 日本  为首的轴心国悍 ...

  7. 听说火狐浏览器的图标里没了狐狸,网友们开始了反极简主义斗争

    "请您坐到设计师工位上来." 1 企业或产品的LOGO,是一种独有且特异的标志,能够最直观且最形象地体现企业及产品的功能与风貌.如果企业及产品的功能有所变化或升级,LOGO也会顺着 ...

  8. 使用python构建数据库_使用Python构建一个极简主义博客(或者,如何学习停止烦恼和热爱Web开发)。

    使用python构建数据库 As of today, I have taken my final examination as an undergraduate student of Physics. ...

  9. Spring Boot(5)一个极简且完整的后台框架

    一个完整的极简后台框架,方便做小项目的时候可以快速开发. 这里面多贴图片和代码,做个参考吧,代码可以下载下来自己看看,里面这套后台模板不错,喜欢的拿去. 先放几张图 项目介绍 SpringBoot,我 ...

最新文章

  1. jQuery使用经验建议
  2. thymeleaf 中文_springboot 整合 thymeleaf(上手即用)
  3. CentOS设置文本启动方式(命令行模式)
  4. 西瓜书学习记录-模型评估与选择(第二章)
  5. etcd raft library设计原理和使用
  6. Select 可编辑 - 完美支持各大主流浏览器
  7. linux中dhcp如何配置两个子网,linux – 配置DHCP服务器以在同一VLAN上为多个子网提供服务...
  8. python requests cookie_python requests 带cookie访问页面
  9. Beta冲刺 day7
  10. Mongo 用户创建及权限管理
  11. 蓝桥杯 ALGO-60 算法训练 矩阵乘方
  12. 使用ffmpege转为mkv到mp4
  13. 最新全国五级行政区划json文件下载链接 全国最新统计用区划代码和城乡划分代码使用指南
  14. 再聊一聊测试职业发展
  15. 飞猪研报:知识xingqiu
  16. torch Dataloader中的num_workers
  17. 基于特征匹配的英文印刷字符识别代码自己的注释
  18. (简单)华为畅玩5C NEM-AL00的usb调试模式在哪里打开的教程
  19. 川崎机器人总线通信_川崎机器人:PLC有那些功能?能实现机器人哪些通讯?
  20. ESP32-C3学习,Windows下基于VScode环境建立

热门文章

  1. Oracle创建Database Link的两种方式
  2. MYC-Y6ULY2文件系统裁剪记录
  3. 网段、子网掩码计算方法
  4. YOLO训练自己的数据集的一些心得
  5. C语言assert函数完全攻略
  6. matlab ceiling,ceiling_excel中ceiling函数的用法?
  7. Zotero 中英文文献通用快捷引用方法
  8. 地质灾害公开数据库有哪些,网址是什么
  9. Java-使数值不使用科学计数法
  10. Ruby On Rails 常用的精品Gem汇总