Chinaunix首页 | 论坛 | 博客
  • 博客访问: 21333
  • 博文数量: 2
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 80
  • 用 户 组: 普通用户
  • 注册时间: 2014-12-15 12:35
文章分类
文章存档

2014年(2)

我的朋友

分类: Python/Ruby

2014-12-23 10:15:26

CherryPy - Start the Turtorial(1)

                                        作者:hhdong

1.  脚本Hello.py

点击(此处)折叠或打开

  1. import cherrypy
  2. class HelloWorld(object):
  3.     def index(self):
  4.         return "Hello world!"
  5.     index.exposed = True
  6. cherrypy.quickstart(HelloWorld())


(1) import cherrypy - 导入cherrypu这个包。之后可以在python环境下使用help(cherrypy)来查看这个包的使用。

(2) class HelloWorld(object) - 声明一个类,这个类的一个实例通过cherrypy.quickstart发布。

此例中,该类仅有一个index方法,当浏览器访问HelloWorld实例对应的根URL时,(如本例中),该index方法将被调用。在此index返回网页对应的内容。

(3) index.exposed = True  表示此方法是exposed的,只有exposed的方法才能够被调用了来响应浏览器的的请求。这个特定可以被用户用来确定类的对象的哪些方法可以被web访问。decorator cheerypy.expose()和上述的method.exposed = True实际作用是一样的。

(4) cherrypy.quickstart(HelloWordl())用来mount类的实例并启动cherrypy内钱的web服务器。可以通过Ctrl-C来中断

CherryPy structure

CherryPy包包含下面一些模块:

cherrypy.engine - 用于控制进程的启动,关闭和其它一些事件,还包含插件等

cherrypy.server - 配置和控制HTTP服务器

cherrypy.request - 包含所有来自HTTP请求,并经过CherryPY分析和处理的全部信息

cherrypy.request.headers - 包含来自于请求的头信息

cherrypy.session - CherryPy自动产生和编码,可用于将会话数据存储在cookie中。为了使其工作,需要在config中设置tools.session.on

cherrypy.response - 包含所有用于构建HTTP响应的所有数据

cherrypy.response.headers - 包含HTTP响应的头

cherrypy.response.body - 以响应的形式发送的实际内容

CherryPy Response
cherrypy.response对象的存在用于影响对请求的响应。与reques一样,response对象是基于线程的,即尽管其是全局变量,但是其值是当前进程独有的。

HTTP Headers

cherrypy.requestcherrypy.response的头属性用于表示request header(由客户端发送的)和response header(发送给客户端的)

例子如下:


点击(此处)折叠或打开

  1. import cherrypy
  2. class HelloWorld(object):
  3.     @cherrypy.expose
  4.     def index(self):
  5.         host = cherrypy.request.headers['Host']
  6.         return "You have successfully reached " + host
  7. cherrypy.quickstart(HelloWorld())


其将返回浏览器访问host

 点击(此处)折叠或打开

  1. import cherrypy
  2. class HelloWorld(object):
  3.     def _get_jpeg_data(self):
  4.         """This method should return the jpeg data"""
  5.         return ""
  6.     @cherrypy.expose
  7.     def index(self):
  8.         cherrypy.response.headers['Content-Type'] = 'application/jpeg'
  9.         return self._get_jpeg_data()
  10.  
  11. cherrypy.quickstart(HelloWorld())


设置响应的头属性

2.  Exposing

Exposing objects

CherryPy能够将URL请求与处理该URL请求的函数映射起来。这就需要靠exposed.

CherryPy中需要将一个objects exposed的话,设置该objectexposed属性。


点击(此处)折叠或打开

  1. import cherrypy
  2. class Root(object):
  3.     def index(self):
  4.         """Handle the /URL """
  5.     index.exposed = True
  6. cherrypy.quickstart(Root())


或者
点击(此处)折叠或打开

  1. import cherrypy
  2. class Root(object):
  3.     @cherrypy.expose
  4.     def index(self):
  5.         """Handle the / URL"""
  6.         return 'Hello world!'
  7. cherrypy.quickstart(Root())


设置一个方法exposed,可通过注入index.exposed属性, 这个decorator

 点击(此处)折叠或打开

  1. """This example can handle the URLs
  2. / -> Root.index
  3. /page -> Root.page
  4. /node -> Node.__call__
  5. """
  6. import cherrypy
  7. class Node(object):
  8.     exposed = True
  9.     def __call__(self):
  10.         return "The node content"
  11. class Root(object):
  12.     def __init__(self):
  13.         self.node = Node()
  14.     @cherrypy.expose
  15.     def index(self):
  16.         return "The index of the root object"
  17.     def page(self):
  18.         return "This is the page content"
  19.     page.exposed = True
  20.  
  21. if __name__ == '__main__':
  22. cherrypy.quickstart(Root())


上面的程序中,URL ‘/’ 对应的callback函数是Root.index/page对应的callback函数是Root.page。对于/node,则处理如下:

(1)在Root.__init__中,设定self.node = Node()。而由于需要回调函数是Node.__call__,故类Node通过设置其exposed属性为True


3. Dispatching


当用户想要在web上提供资源服务时,CherryPy通过page handlers来提供资源的表示的形式来提供服务。Page handlers是指用户所写的函数:CherryPy通过调用它来响应每个请求,并使用它向客户端发出响应。

CherryPypage handlers函数的合适输出与cherrypy.response.body绑定在一起,作为HTTP响应体发送出去。page handlers可以根据需要直接设置cherrypy.response.statuscherrypy.response.headers.

Disptachers

CherryPy能够调用page handler之前,其需要知道:

1)这些page handlders的位置

2page handlersURI identifier的对应关系。

Dispatcher对象就是为了完成上述功能的。其完成的功能:

1. 理解page handlers的分布

2. URI找到合适的page handler函数

3. 将用户真正的page handler函数打包到PageHandler对象

4. 设置cherrypy.request.handlerPageHandler对象

5. 收集配置到cherrypy.request.config

6. 收集“虚拟路径”组件

Default Dispatcher

CherryPy的默认分配器是一种直观的方式处理URLpage handlers之间的对应关系。例子如下:

     root = HelloWorld()

     root.onepage = OnePage()

     root.otherpage = OtherPage()

URL对应的是Application.root。实际上查看cherrypy.quickstart的源代码就会发现,当调用cherrypy.quickstart(HelloWorld()),其就等效于Application.root = HelloWorld()。当访问时,CherryPy就会在Application.root下查找其最为匹配的函数,对于上面的例子来说,最匹配的就是root.onepage了。同理,最匹配的就是root.otherpage了。

再如下面的例子:

root.some = Page()

root.some.page = Page()

当访问,通过查找,可发现最匹配的是root.some.page这一个对象。

Normal methods :
CherryPy
能直接在mounted objects上调用方法。如下:

点击(此处)折叠或打开

  1. """This example can handel the URIs
  2. / -> OnePage.index
  3. /foo -> OnePage.foo -> foo
  4. """
  5. import cherrypy
  6. class OnePage(object):
  7.     def index(self):
  8.         return "one page!"
  9.     index.exposed = True
  10.  
  11. def foo():
  12.     return "Foo!"
  13. foo.exposed = True
  14.  
  15. if __name__ == '__main__':
  16.     root = OnePage()
  17.     root.foo = foo
  18.     cherrypy.quickstart(root)


root.foo方法直接与foo()函数关联。该函数是的映射函数。

Index methods
index
方法在CherryPy中有较为特别。它通常对应以’/’结尾的URI。例如/orders/items/对应root.orders.item.indexindex方法能够有查询字符串参数或POST参数,但是不能像别的方法一样有位置参数positional arguments.

默认的分配器通常会为以’/’结尾的URI寻找index方法。可以通过HTTPRedirect改变这种情况

 

Keyword Arguments
CherryPy
调用的page handler,如Index或其它函数,能够从HTML或其它forms接收数据信息。例如下面例子用POST方法发送forms参数usernamepassword

点击(此处)折叠或打开

  1. import cherrypy
  2.  
  3. class Root(object):
  4.     @cherrypy.expose
  5.     def index(self):
  6.         return '''
  7.         

  8.           

    Username


  9.           
  10.           

    Password


  11.           
  12.           


  13.           


  14.         
  15.         '''
  16.     @cherrypy.expose
  17.     def doLogin(self, username=None, password=None):
  18.         """Check the username & password"""
  19.  
  20. cherrypy.quickstart(Root())


CherryPy支持HTML 表单的GET和POST方法。


Positional Arguments 
Positional arguments
是指客户端发送请求时,其URI被分割成不同的组成部分,依次与树中的节点对应(其中树是指将app.root看成是根,而其函数则看成是树种的节点)。例如URI “/branch/leaf/4”则可以跟page handler app.root.branch.leaf(4)对应,也可以是跟app.root.index(branch, leaf, 4)对应。可见这种对应不是一一隐身的关系。

如果将URI分割后的不同组成部分不能完完全全的与树对应的话,则采用部分对应的方法。例如URL http://localhost/blog/2005/01/17这个地址,会对应下列代码中的blog()

点击(此处)折叠或打开

  1. import cherrypy
  2.  
  3. class Root(object):
  4.     def blog(self, year, month, day):
  5.         """Deliver the blog post. According to year month day"""
  6.     blog.exposed = True
  7.  
  8. root = Root()
  9. cherrypy.quickstart(root)


Default methods
当默认的分配器不能为URI找到合适的page handler时,其最后会将其交给defalt method来处理。default method和前边提到的__call__具有同样的功能。

点击(此处)折叠或打开

  1. import cherrypy
  2.  
  3. class Blog(object):
  4.     @cherrypy.expose
  5.     def default(self, year, month, day):
  6.         """This method catch the positional arguments"""
  7.  
  8. class Root(object):
  9.     pass
  10.  
  11. root = Root()
  12. root.blog = Blog()
  13.  
  14. cherrypy.quickstart(root)
 当访问/blog/2000/10/10,其最后会由root.blog.default()来处理


Other Dispatchers

有时候,开发者不喜欢上述的默认分配器,因为随着开发的深入,会很难维护或修改page handler树。更喜欢采用hash表或dict的方式来控制。

点击(此处)折叠或打开

  1. import cherrypy
  2.  
  3. def root_index(name):
  4.     print "root_index"
  5.     return "Hello, %s!" % name
  6.  
  7. def branch_leaf(size):
  8.     print "brancher"
  9.     return str(int(size)+3)
  10.  
  11. mappings = [(r'^/([^/]+)$', root_index), (r'^/branch/leaf/(\d+)$', branch_leaf),]
上述例子很让人费解,难道是将mappings作为参数传递给CherryPy的某个函数就能够实现将正则表达式表示的URL和对应的处理handler联系起来吗?


看起来到目前为止,实际上是不能够直接传递上述mappings的方式来建立正则表达式URLhandler之间的联系的。而是要采用下面所述的connect方法来建立URLhandler之间的mapping.

点击(此处)折叠或打开

  1. import cherrypy
  2.  
  3. def root_index(name):
  4.     print "root_index"
  5.     return "Hello, %s!" % name
  6.  
  7. def branch_leaf(size):
  8.     print "brancher"
  9.     return str(int(size)+3)
  10.  
  11. d = cherrypy.dispatch.RoutesDispatcher()
  12. d.connect('hello', '/hello/{name:([^/]+)}', root_index)
  13. conf = {'/':{'request.dispatch':d}}
  14. cherrypy.tree.mount(root=None, config=conf)
  15. cherrypy.engine.start()
注意:如果上述过程中提示d=cherrypy.dispatch.RoutesDispatcher()有错误,模块routes没有找到的话。利用pip install routes安装routes模块。重新执行即可。

原文请参考:CherryPy Documentation Release 3.3.0






阅读(3375) | 评论(0) | 转发(0) |
0

上一篇:一个错误的Python文件名引发的问题

下一篇:没有了

给主人留下些什么吧!~~