CherryPy is a pythonic, object-oriented web framework.官网 ;GitHub 
安装 
直接执行 $ pip install cherrypy。
1 2 3 $ git clone https://github.com/cherrypy/cherrypy $ cd cherrypy $ python setup.py install 
用测试用例检验是否安装成功,直接执行 
$ python -m cherrypy.tutorial.tut01_helloworld。
打开页面http://127.0.0.1:8080 或者http://localhost:8080 查看结果。
一旦成功,控制台也会显示log:
1 2 3 4 5 6 7 8 ENGINE Listening for SIGHUP. ENGINE Listening for SIGTERM. ENGINE Listening for SIGUSR1. ENGINE Bus STARTING ENGINE Started monitor thread 'Autoreloader'. ENGINE Started monitor thread '_TimeoutMonitor'. ENGINE Serving on http://127.0.0.1:8080 ENGINE Bus STARTED 
Hello World 页面部署 
1 2 3 4 5 6 7 8 9 import  cherrypyclass  HelloWorld (object     @cherrypy.expose     def  index (self ):         return  "Hello world!"  if  __name__ == '__main__' :    cherrypy.quickstart(HelloWorld()) 
运行此程序后,控制台则会显示:
1 2 3 4 5 6 7 8 9 10 11 ENGINE Listening for SIGHUP. ENGINE Listening for SIGTERM. ENGINE Listening for SIGUSR1. ENGINE Bus STARTING CherryPy Checker: The Application mounted at '' has an empty config. ENGINE Started monitor thread 'Autoreloader'. ENGINE Started monitor thread '_TimeoutMonitor'. ENGINE Serving on http://127.0.0.1:8080 ENGINE Bus STARTED 
前三行表示服务器会处理signal;第四行表示服务器的状态,此刻在启动阶段;第五、六行表示你的应用没有特别的配置;第八、九行表示服务器开始了一些内部的功能,倒数第二行表示已经准备好通信并且监听地址127.0.0.1:8080,最后一行表示现在你的应用已经开始运行,可以使用。
这里return为index页面的源码:
- 可以是一般字符串,比如 
"Hello world!",页面直接显示字符串
- 可以是
HTML 格式的字符串,比如
1 2 3 4 5 6 7 8 9 10 11 12 13 14 """ <html>     <head>         <script type="text/javascript" src="/xxx/xxx/xxx.js"></script>         <title>Write Your WebPage Title Here</title>         <link rel="stylesheet" type="text/css" href="/xxx/xxx/xxx.css" />     </head>     <body>         <div class="xxx">             Hello world!         </div>     </body> </html> """ 
这里使用三对双引号,用来输入多行文本,之中的单号和双引号不用转义,其中的不可见字符比如。
- 可以是HTML文件 
open('xxx/xxx/xxx.html')
注打开文件的时候可以传递参数
open("xxx.html").read().format(a=a, b=b, c=c, ...),则HTML文件中 
{a:}; 
{b:}; 
{c:}; ...来表示相应的字符串。
或者 
open("xxx.html").read() % (a, b, c, ...),HTML文件中 
%s;
%d;
%f 等来表示相应位置的字符串。
原理:
open("xxx.html").read() 返回一个string对象,传递参数同格式化输出。
用 cherrypy.quickstart() 启动单个应用,此函数至少需要一个参数,第一个必选一般为类名;第二个可选参数为应用访问的基础路径;第三个可选参数为应用配置。cherrypy.tree.mount(),此函数的参数和 cherrypy.quickstart() 一样,均为一个应用的类名,一个主机路径,一个配置。举例如下
1 2 3 4 5 cherrypy.tree.mount(A(), '/a' , a_conf) cherrypy.tree.mount(B(), '/b' , b_conf) cherrypy.engine.start() cherrypy.engine.block() 
不同的 URLs 对应不同的 functions 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import  randomimport  stringimport  cherrypyclass  StringGenerator (object     @cherrypy.expose     def  index (self ):         return  "Hello world!"      @cherrypy.expose     def  generate (self ):         return  '' .join(random.sample(string.hexdigits, 8 )) if  __name__ == '__main__' :    cherrypy.quickstart(StringGenerator()) 
运行此程序后,打开 http://localhost:8080 或者 http://localhost:8080/index 则会显示 Helloworld 界面(index 可以省略)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import  randomimport  stringimport  cherrypyclass  StringGenerator (object     @cherrypy.expose     def  index (self ):         return  "Hello world!"      @cherrypy.expose     def  default (self, url ):         return  '' .join(random.sample(string.hexdigits, 8 )) if  __name__ == '__main__' :    cherrypy.quickstart(StringGenerator()) 
运行此程序后,打开http://localhost:8080/xxx 则会运行default函数并返回且显示一个8位随机字符串,这里xxx为任意网址。
注意,default函数必须有两个参数,url会传入用户所访问的网址,即 
url=xxx
通过 URL 传递参数 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import  randomimport  stringimport  cherrypyclass  StringGenerator (object     @cherrypy.expose     def  index (self ):         return  "Hello world!"      @cherrypy.expose     def  generate (self, length=8  ):         return  '' .join(random.sample(string.hexdigits, int (length))) if  __name__ == '__main__' :    cherrypy.quickstart(StringGenerator()) 
运行此程序后,打开 http://localhost:8080/generate?length=16 ,
提交表单 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import  randomimport  stringimport  cherrypyclass  StringGenerator (object     @cherrypy.expose     def  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.expose     def  generate (self, length=8  ):         return  '' .join(random.sample(string.hexdigits, int (length))) if  __name__ == '__main__' :    cherrypy.quickstart(StringGenerator()) 
运行此程序后,打开 http://localhost:8080/ ,填写表格并提交。
Session 
一个应用经常需要追踪用户的行为,一个常用的做法是使用 session 暂存数据,并且在客户端服务器通信中保持。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 import  randomimport  stringimport  cherrypyclass  StringGenerator (object     @cherrypy.expose     def  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.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) 
运行此程序后,打开http://localhost:8080/generate 生成一个随机字符串并存入session的'mystring'字段之中。
打开http://localhost:8080/display 展示session中存储的字符串。
CherryPy会存储session的信息在进程的内存中。
注意此时要修改.conf文件。
1 2 [/] tools.sessions.on = True 
Cookies 
CherryPy 使用 Python 模块 Cookie,Cookie.SimpleCookie 对象来处理 cookiecherrypy.response.cookie[key] = valuecherrypy.request.cookie[key]cherrypy.response.cookie[key]['expires'] = 0
允许文件上传、下载 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 import  osimport  os.pathimport  cherrypyfrom  cherrypy.lib import  staticlocalDir = os.path.dirname(__file__) absDir = os.path.join(os.getcwd(), localDir) class  FileDemo (object     @cherrypy.expose     def  index (self ):         return  """          <html><body>             <h2>Upload a file</h2>             <form action="upload" method="post" enctype="multipart/form-data">             filename: <input type="file" name="myFile" /><br/>             <input type="submit" />             </form>             <h2>Download a file</h2>             <a href='download'>This one</a>         </body></html>         """     @cherrypy.expose     def  upload (self, myFile ):         out = """<html>          <body>             myFile length: %s<br />             myFile filename: %s<br />             myFile mime-type: %s         </body>         </html>"""         size = 0          while  True :             data = myFile.file.read(8192 )             if  not  data:                 break              size += len (data)         return  out % (size, myFile.filename, myFile.content_type)     @cherrypy.expose     def  download (self ):         path = os.path.join(absDir, 'pdf_file.pdf' )         return  static.serve_file(path, 'application/x-download' , 'attachment' , os.path.basename(path)) if  __name__ == '__main__' :    cherrypy.quickstart(FileDemo()) 
上传 :下载 :serve_file(path, content_type=None, disposition=None, name=None, debug=False) 函数:第一个参数为文件路径;第二个参数为内容类型;第三个参数为 Content-Disposition 信息(Content-Disposition 就是当用户想把请求所得的内容存为一个文件的时候提供一个默认的文件名),如果不为空,则 Content-Disposition header 会被设置为 "<disposition>; filename=<name>",如果 name 为空,则 name 被设置为文件的 basename。
以流形式处理请求主体 
CherryPy 收到 HTTP 请求后,对于底层信心进行处理后将请求传给页面处理部分,这里就会生成请求主体 (response body).response.stream = true 并结合 yield,示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import os.path import cherrypy class HelloWorld(object):     @cherrypy.expose     def index(self):         yield "Hello "         yield "world!" if __name__ == '__main__':     conf = {         '/': {             'response.stream': True         }     }     cherrypy.quickstart(HelloWorld(), '/', conf) 
调用网站资源 
网络应用经常会调用一些静态资源,比如 JavaScript ,CSS  或 image 等资源。<script type="text/javascript" src="/static/js/xxx.js"></script><link rel="stylesheet" type="text/css" href="/static/css/xxx.css" /><img src="/static/image/xxx.jpg" alt="xxx" style="width:123px;height:123px;">
1 2 3 4 5 6 [/] tools.staticdir.root = os.path.abspath(os.getcwd()) [/static] tools.staticdir.on = True tools.staticdir.dir = "public" 
对于独立文件资源:
1 2 3 [/style.css] tools.staticfile.on = True tools.staticfile.filename = filepath 
REST 
客户端除了浏览器之外,还有其他一些形式比如 python,iOS,Android 等。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 import  randomimport  stringimport  cherrypy@cherrypy.expose class  StringGeneratorWebService (object     @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) 
运行此程序后,可以使用python的requests库来进行交互。
这里通过@cherrypy.expose装饰器一次性暴露StringGeneratorWebService类的所有方法。
该应用不再是以<URL,函数>匹配的方式进行工作,而是在配置里面创建了cherrypy.dispatch.MethodDispatcher实例,用于自动匹配。
对于get函数强制response的contenttype为text/plain。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 >>>  import  requests>>>  s = requests.Session()>>>  r = s.get('http://127.0.0.1:8080/' )>>>  r.status_code500  >>>  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_code406  >>>  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_code500  
AJAX 
AJAX  = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)。更新部分 网页的技术。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 import  os, os.pathimport  randomimport  stringimport  cherrypyclass  StringGenerator (object     @cherrypy.expose     def  index (self ):         return  '''<!DOCTYPE html>                      <html>                       <head>                         <style>                           #the-string {                             display: none;                           }                         </style>                         <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) {                               $.ajax({                                 type: "POST",                                 url: "/generator",                                 data: {"length": $("input[name='length']").val()}                               })                               e.preventDefault();                             });                             $("#replace-string").click(function(e) {                               $.ajax({                                 type: "PUT",                                 url: "/generator",                                 data: {"another_string": $("#the-string input").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>                     ''' @cherrypy.expose class  StringGeneratorWebService (object     @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' )],         },     }     webapp = StringGenerator()     webapp.generator = StringGeneratorWebService()     cherrypy.quickstart(webapp, '/' , conf) 
运行此程序后,可以使用按钮触发ajax结合
jQuery 来进行交互。
其中:
1 2 3 4 5 6 7 8 9 10 11 12 $("#generate-string" ).click(function (e )    $.ajax({     type : "POST" ,     url : "/generator" ,     data : {"length" : $("input[name='length']" ).val()}   })    .done(function (string )      $("#the-string" ).show();     $("#the-string input" ).val(string);   });   e.preventDefault(); }); 
表示当id为generate-string的按钮被点击后,执行POST命令,目标url是generator,以
JSON 方式传参数length,length的值为名字等于length的input组件的值。完成POST后服务器返回string,并且将id为the-string的组件显示出来,将其input组件的值赋值为string。
1 2 3 4 5 6 7 8 9 10 11 $("#replace-string" ).click(function (e )    $.ajax({     type : "PUT" ,     url : "/generator" ,     data : {"another_string" : $("#the-string input" ).val()}   })   .done(function (     alert("Replaced!" );   });   e.preventDefault(); }); 
表示当id为replace-string的按钮被点击后,执行PUT命令,目标url是generator,以JSON方式传参数another_string,another_string的值为id为the-string的组件中的input组件的值。完成PUT后弹出警告框"Replaced"。
1 2 3 4 5 6 7 8 9 10 $("#delete-string" ).click(function (e )    $.ajax({     type : "DELETE" ,     url : "/generator"    })   .done(function (     $("#the-string" ).hide();   });   e.preventDefault(); }); 
表示当id为delete-string的按钮被点击后,执行DELETE命令,目标url是generator,完成DELETE后将id为the-string的组件隐藏。
数据库存储 
这里以 SQLite 数据库为例,演示如何将网页数据存入数据库 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 import  os, os.pathimport  randomimport  sqlite3import  stringimport  timeimport  cherrypyDB_STRING = "my.db"  class  StringGenerator (object     @cherrypy.expose     def  index (self ):         return  '''<!DOCTYPE html>                      <html>                       <head>                         <style>                           #the-string {                             display: none;                           }                         </style>                         <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) {                               $.ajax({                                 type: "POST",                                 url: "/generator",                                 data: {"length": $("input[name='length']").val()}                               })                               e.preventDefault();                             });                             $("#replace-string").click(function(e) {                               $.ajax({                                 type: "PUT",                                 url: "/generator",                                 data: {"another_string": $("#the-string input").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>                     ''' @cherrypy.expose class  StringGeneratorWebService (object     @cherrypy.tools.accept(media='text/plain'  )     def  GET (self ):         with  sqlite3.connect(DB_STRING) as  c:             cherrypy.session['ts' ] = time.time()             r = c.execute("SELECT value FROM user_string WHERE session_id=?" ,                           [cherrypy.session.id ])             return  r.fetchone()     def  POST (self, length=8  ):         some_string = '' .join(random.sample(string.hexdigits, int (length)))         with  sqlite3.connect(DB_STRING) as  c:             cherrypy.session['ts' ] = time.time()             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:             cherrypy.session['ts' ] = time.time()             c.execute("UPDATE user_string SET value=? WHERE session_id=?" ,                       [another_string, cherrypy.session.id ])     def  DELETE (self ):         cherrypy.session.pop('ts' , None )         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' )],         },     }     cherrypy.engine.subscribe('start' , setup_database)     cherrypy.engine.subscribe('stop' , cleanup_database)     webapp = StringGenerator()     webapp.generator = StringGeneratorWebService()     cherrypy.quickstart(webapp, '/' , conf) 
运行此程序后,可以使用按钮触发ajax来进行交互。
大部分功能与上一个例子相同,这里增加了将session中的数据存入数据库的功能。
其中 
cherrypy.engine.subscribe('start', setup_database) 和 
cherrypy.engine.subscribe('stop', cleanup_database) 表示setup_database函数和cleanup_database函数被注册到服务器,当服务器启动和停止时调用。
setup_database函数新建一个名为user_string的表格,cleanup_database函数删除user_string表格。
日志记录 
CherryPy 会记录所有的 requests 和协议错误。cherrypy.log()。log.access_file 记录 requests 情况log.error_file 记录其他的情况
修改.conf 文件。
1 2 3 4 [/] log.screen = False, #用于取消console的logging log.access_file = "access.log", log.error_file = "error.log", 
服务器配置 
全局配置 (global) 
HTTP 配置
1 2 3 4 [global] server.socket_host = "127.0.0.1" server.socket_port = 8080 server.thread_pool = 10 
HTTPS配置
1 2 3 4 5 6 7 [global] server.socket_host = "0.0.0.0" server.socket_port = 443 server.thread_pool = 10 server.ssl_module = 'builtin' server.ssl_certificate = "cert.pem" server.ssl_private_key = "privkey.pem" 
可以用OpenSSL工具生成自签名的证书,方法如下:
$ openssl genrsa -out privkey.pem 2048 #用于生成私钥修改 OpenSSL.cnf 配置文件(最好不修改此目录下的文件,而是拷贝一份至你的生成证书的目录) 
找到 [v3_ca] 在其下方加入并保存:1 2 3 subjectAltName = "IP:server的ip" basicConstraints = CA:FALSE keyUsage = digitalSignature, keyEncipherment 
 
$ openssl req -new -x509 -days 365 -key privkey.pem -out cert.pem -config openssl.cnf #用于生成证书cert.pem 的后缀改为 cer 就可以作为证书使用了。 
 
网站 Gzip 
Gzip 开启以后会将输出到用户浏览器的数据进行压缩的处理,这样就会减小通过网络传输的数据量,提高浏览的速度。
其他配置 
也可以将某些字符串存入配置文件,供各种函数访问。
在函数中通过 
jklmn = cherrypy.request.app.config['abc']['def'] 调用,此时jklmn变量被赋值"ghi",str类型。
处理 JSON 
CherryPy 内置支持了对 JSON 编码的请求或响应的解码支持。
解码 request 
自动解码 JSON 请求的内容:
1 2 3 4 @cherrypy.expose @cherrypy.tools.json_in() def  index (self ):    data = cherrypy.request.json 
附加在请求的JSON属性包含解码内容。
编码 response 
使用 JSON 自动编码 response 的内容:
1 2 3 4 @cherrypy.expose @cherrypy.tools.json_out() def  index (self ):    return  {'key' : 'value' } 
CherryPy将使用JSON对你的页面处理程序返回的任何内容进行编码,并非所有类型的对象都可以被编码。
认证 
CherryPy 提供了两种非常简单的身份验证机制。他们最常见的触发方式是触发浏览器弹出窗口向用户询问他们的名字和密码。
Basic 
Basic 身份验证是最简单的验证方式,但它不是一个安全的身份验证,因为用户的凭证被嵌入到请求中。不建议使用它,除非你在 SSL 或封闭的网络中运行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 from  cherrypy.lib import  auth_basicUSERS = {'id' : 'password' } def  validate_password (realm, username, password ):    if  username in  USERS and  USERS[username] == password:        return  True      return  False  conf = {    '/protected/area' : {        'tools.auth_basic.on' : True ,        'tools.auth_basic.realm' : 'localhost' ,        'tools.auth_basic.checkpassword' : validate_password     } } cherrypy.quickstart(myapp, '/' , conf) 
必须提供一个将有CherryPy调用的函数,解码从请求中传递的用户名和密码。
该功能可以从任何来源读取数据:文件,数据库,内存等。
Digest 
Digest 认证的不同之处在于,凭证没有携带在请求中,因此比 Basic 更安全。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 from  cherrypy.lib import  auth_digestUSERS = {'id' : 'password' } conf = {    '/protected/area' : {         'tools.auth_digest.on' : True ,         'tools.auth_digest.realm' : 'localhost' ,         'tools.auth_digest.get_ha1' : auth_digest.get_ha1_dict_plain(USERS),         'tools.auth_digest.key' : 'a565c27146791cfb'     } } cherrypy.quickstart(myapp, '/' , conf) 
网站图标 
CherryPy 提供自己的红色 cherrypy 作为默认图标。可以用以下方式提供自己的图标:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import  cherrypyclass  HelloWorld (object    @cherrypy.expose    def  index (self ):        return  "Hello World!"  if  __name__ == '__main__' :    cherrypy.quickstart(HelloWorld(), '/' ,         {             '/favicon.ico' :             {                 'tools.staticfile.on' : True ,                 'tools.staticfile.filename' : '/path/to/myfavicon.ico'              }         }     ) 
也可以使用文件进行配置:
1 2 3 [/favicon.ico] tools.staticfile.on: True tools.staticfile.filename: "/path/to/myfavicon.ico" 
1 2 3 4 5 6 7 8 9 import  cherrypyclass  HelloWorld (object    @cherrypy.expose    def  index (self ):        return  "Hello World!"  if  __name__ == '__main__' :    cherrypy.quickstart(HelloWorld(), '/' , app.conf) 
设置页面别名 
1 2 3 4 5 6 7 8 9 10 11 import  randomimport  stringimport  cherrypyclass  StringGenerator (object     @cherrypy.expose(['generer' , 'generar' ] )     def  generate (self, length=8  ):         return  '' .join(random.sample(string.hexdigits, int (length))) if  __name__ == '__main__' :    cherrypy.quickstart(StringGenerator()) 
其中 @cherrypy.expose(['generer', 'generar']) 设置了别名,所以下面三个页面效果是一样:/generate;/generer (French);/generar (Spanish)
请求超时 
CherryPy 包含 3 个时间相关的属性:
可以通过 response.check_timeout 来检查是否超时,在激活超时机制的情况下,一旦超时则触发 TimeoutError 异常。
1 2 [global] engine.timeout_monitor.on: False 
或者
1 cherrypy.engine.timeout_monitor.unsubscribe() 
默认超时监控是1分钟1次,改成1小时1次:
1 2 [global] engine.timeout_monitor.frequency: 60 * 60 
信号处理 
对于信号处理,有一个 cherrypy.engine.signal_handler 插件,它是被 cherrypy.quickstart () 自动调用的。tree.mount() 或 engine.start() 或 engine.block()。engine.signals.subscribe()。