添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

2 SWGI( Web Server Gateway Interface )

早期Python应用程序通常是为 CGI , FastCGI , mod_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

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.expose
    def index(self):
        return "Hello World!"
cherrypy.quickstart(HelloWorld())
    def 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
@cherrypy.expose def 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.expose
    def index(self):
        return """<html>
          <head></head>
            <form method="get" action="generate">
              <input type="text" value="8" name="length" />
              <button type="submit">Give it now!</button>
            </form>
          </body>
        </html>"""
    @cherrypy.expose
    def 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.expose
   def index(self):
       return """<html>
         <head></head>
       <form method="get" action="generate">
         <input type="text" value="8" name="length" />
             <button type="submit">Give it now!</button>
       </form>
     </body>
   </html>"""
   @cherrypy.expose
   def generate(self, length=8):
       some_string = ''.join(random.sample(string.hexdigits, int(length)))
       cherrypy.session['mystring'] = some_string
       return some_string
   @cherrypy.expose
   def 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结构
return """<html> <link href="http://lesliezhu.github.com/static/css/style.css" rel="stylesheet"> </head> <form method="get" action="generate"> <input type="text" value="8" name="length" /> <button type="submit">Give it now!</button> </form> </body> </html>""" @cherrypy.expose def generate(self, length=8): some_string = ''.join(random.sample(string.hexdigits, int(length))) cherrypy.session['mystring'] = some_string return some_string @cherrypy.expose def 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_string
        return some_string
    def PUT(self, another_string):
        cherrypy.session['mystring'] = another_string
    def 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
>>> 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
>>> 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
 

11 支持Ajax

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

一个使用 jQuery框架 的例子:

import os, os.path
import random
import string
import cherrypy
class StringGenerator(object):
   @cherrypy.expose
   def 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_string
        return some_string
    def PUT(self, another_string):
        cherrypy.session['mystring'] = another_string
    def 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>
     <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>
     <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>
   </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.path
 import random
 import sqlite3
 import string
 import cherrypy
 DB_STRING = "my.db"
 class StringGenerator(object):
    @cherrypy.expose
    def 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_string
     def 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 database
     on 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 database
     on 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
  • 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/
目录1 前言2 SWGI(Web Server Gateway Interface)3 特色与优势4 Hello, World!5 不同URL调用不同函数6 带有参数的URL7 处理表单8 跟踪终端用户状态9 支持静态内容(javascript,css,images)10 支持REST(Representational State Transfer)11 支持Ajax12 支持数据存储
最近几天在看CherrPy,中文资料很少所以打算看文档的时候顺便翻译下来,希望能给需要的朋友一点帮助。   前面几节已经有中文版了,附上连接点击打开链接   这里从Basics这一章开始 一分钟的应用实例: 你可以使用CherryPy编写的最基本的web应用程序,几乎涉及其所有核心概念。 import cherrypy class Root(object): @cherry
CherryPy,一种用于 Python 的、简单而又非常有用的 Web 框架。它所做的全部工作就是以尽可能少的忙乱将 Web 服务器与您的 Python 代码连接。它并不决定使用哪些其他工具,所以您可以从自己的角度自由地选择模板系统、数据库映射程序或者其他工具。 CherryPy 请求 CherryPy 不是依靠 Apache 或者另外的 Web 服务器,而是运行它自己的小型的基于 ...
最近在项目学习中,需要用到cherrypy web框架,现将学习过程记录如下。 CherryPy是一种用于 Python 的、简单而又非常有用的 Web 框架。它所做的全部工作就是以尽可能少的代码将 Web 服务器与 Python 代码连接。它并不决定使用哪些其他工具,所以可以从自己的角度自由地选择模板系统、数据库映射程序或者其他工具。 1、cherrypy请求 CherryPy 不是依靠 Apache 或者另外的 Web 服务器,而是运行它自己的小型的基于 PythonWeb 服务器。传统的 Web
Python 有很多不同的 Web 框架可供选择。以下是一些最受欢迎的 Python Web 框架: 1. Django:Django 是 Python 最流行的 Web 框架之一,用于开发复杂的 Web 应用程序。它有一个庞大的社区,提供了许多功能强大的工具和库,如 ORM、表单处理和安全性。 2. Flask:Flask 是一个轻量级 Web 框架,简单易用,适用于开发小型 Web 应用程序和 API。它具有灵活性和可扩展性,可以根据需求选择添加需要的插件和库。 3. Pyramid:Pyramid 是一个功能强大的 Web 框架,专注于灵活性和可扩展性。它具有大量的插件和库,适用于开发大型和复杂的 Web 应用程序。 4. Bottle:Bottle 是一个轻量级 Web 框架,代码简单易懂,适用于开发小型 Web 应用程序和 API。它内置了一个简单的模板引擎,可以轻松处理 HTTP 请求和响应。 5. CherryPyCherryPy一个 Web 框架,可以帮助开发人员构建高性能的 Web 应用程序和服务。它可以直接运行在多种服务器上,例如 Apache、IIS 和 Nginx。 以上是一些最流行的 Python Web 框架,每个框架都有其独特的特点和优势,可以根据自己的需求和项目的要求选择合适的框架