zoukankan      html  css  js  c++  java
  • Python WSGI

    参考

    因为服务都以restful api的方式提供给外界访问,于是又要看WSGI,要用到PasteDeploy库,但是感觉资料有些难懂尤其是paste.ini的使用上,下面几篇还算不错

    [1] http://wanglianghuaihua.blog.163.com/blog/static/5425153120138273471531/

    [2] http://pythonpaste.org/deploy/ ([1]是对[2]的翻译,不过有些部分没有在[1]中出现,看看原文还是有必要的)

    [3] http://smartzxy.iteye.com/blog/734050 (给了一个实例和一些分析)

    一个简单的WSGI实例

    WSGI的概念不想多扯,在我看来和CGI差不多,和ASP,PHP,serverlet总是那么相似,下面来看一个实例,超简单的一个http动态服务程序(端口8082)

    #! /usr/bin/env python
    
    from wsgiref.simple_server import make_server
    
    import datetime
    def default_wsgi_app(environ, start_response):
    	print 'environment varibles:'
    	for (k, v) in environ.items():
    		print "%15s : %s" % (k, v)
    	
    	status  = '200 OK'
    	headers = [('Content-type', 'text/plain')]
    	start_response(status, headers)
    	
    	return ['HaHa HeHe...generated@',str(datetime.datetime.now())]
    
    httpd = make_server('', 8082, default_wsgi_app)
    httpd.serve_forever()
    

    其中的default_wsgi_app就是一个请求处理过程,把这个函数给make_server创建一个wsgi server(这里是httpd变量),它就会把监听到的请求扔给default_wsgi_app这个函数处理。函数的签名就是WSGI的标准,environ用于表示环境(含有GET/POST参数)变量是一个dict, start_response的使用如上述代码所示,用来输出响应头(HTTP Response Header)(当然可能更复杂,还没看过源码),响应头输出后,就要开始输出响应体(HTTP Response Body),即响应内容。default_wsgi_app函数通过返回一个字符串list来作为请求的响应内容。然后wsgi server接收到default_wsgi_app函数返回内容后,就开始将数据发送到请求端,这样一次请求-响应过程结束了。

    如果我们把这个default_wsgi_app改的复杂一些,加入session保持(通过在http header中设置cookie和服务端的全局变量中创建一个映射),url dispatcher就跟其他的如serverlet非常像了。

    PasteDeploy模块的简单使用

    下面开始介绍PasteDeploy,它可以通过定义一个配置文件(ini格式,非常简单的键值赋值)把各个类似default_wsgi_app的WSGI响应处理函数组织起来(给他们不同的url路径映射),或者在其外围包裹一层filter对请求或者响应的内容做些预/后处理,这跟python的函数装饰器很像。但是我们不能掉进java的坑里面,什么AOP啊一大堆,简单实用又不失结构性的风格是派森大法最有魅力的地方。由于paste的配置文件非常灵活,还是从最简单的开始说起。

    paste.ini

    我们创建一个叫做demo-paste.ini的文件,内容如下:

    [DEFAULT]
    server_name = WSGI DEMO SERVER
    
    [app:main]
    app_developer = hgfeaon
    app_version = 1.0
    paste.app_factory = sample:custom_app_factory
    

    先解释一下,

    • 在[DEFAULT]节中的变量定义都作为全局变量(如server_name)
    • [app:main]表示一个名称为main的WSGI实例的配置,在这里定义的变量作为专门用于这个实例的局部变量(如app_developer, app_version)
    • paste.app_factory = sample:custom_app_factory,表示WSGI的处理函数(如上例中的default_wsgi_app)由谁来生成,这里我们定义由sample模块中的custom_app_factory函数来生成

     paste.app_factory

    其中paste.app_factory是Paste模块的一个参数它指向一个用于创建WSGI处理函数的函数,这个factory函数应该是如下形式:

    paste.app_factory

    The application is the most common. You define one like:

    def app_factory(global_config, **local_conf):
        return wsgi_app
    

    The global_config is a dictionary, and local configuration is passed as keyword arguments. The function returns a WSGI application.

    这个函数有两个入参一个是global_config,是一个dict,内容就是在paste.ini文件中[DEFAULT]一节中定义的变量,而另外一个kwargs型参数local_config也可以看成是一个dict,存储的是每个节中的局部变量。根据这些变量可以定义一个工厂(之所以这样叫是因为用到了工厂模式)函数,来返回不同的WSGI响应函数,或者说对响应函数对象做一些配置。下面给出这个工厂函数(这个文件命名为sample.py和demo-paste.ini放在一个目录下):

    #! /usr/bin/env python
    import datetime
    def default_wsgi_app(environ, start_response):
    	print 'environment varibles:'
    	for (k, v) in environ.items():
    		print "%15s : %s" % (k, v)
    	
    	status  = '200 OK'
    	headers = [('Content-type', 'text/plain')]
    	start_response(status, headers)
    	
    	return ['HaHa HeHe...generated@',str(datetime.datetime.now())]
    
    def custom_app_factory(global_config, **local_config):
    	# print the global variables defined in section [DEFAULT] section
    	print 'Global Config:'
    	for (k, v) in global_config.items():
    		print "%15s : %s" % (k, v)
    	# print the local variables defined in this non-DEFAULT section
    	# where the custom_app_factory is refered as 
    	# paste.app_factory = sample:custom_app_factory
    	print 'Local Config:'
    	for (k, v) in local_config.items():
    		print "%15s : %s" % (k, v)
    	
    	return default_wsgi_app
    

    这里没有真正的使用这些参数,只是把它们打印了一下,然后返回用来处理请求的WSGI处理函数对象(default_wsgi_app)。下面可以通过在python解析器(从两个文件所在的目录启动)中执行以下代码来通过paste模块加载app(WSGI处理程序),注意这里配置文件的位置最好使用绝对路径。

    >>> from wsgiref.simple_server import make_server
    >>> from paste.deploy import loadapp
    >>> wsgi_app = loadapp('config:e:/desktop/cloud_computing/wsgi/demo-paste.ini')
    Global Config:
           __file__ : e:desktopcloud_computingwsgidemo-paste.ini
               here : e:desktopcloud_computingwsgi
        server_name : WSGI DEMO SERVER
    Local Config:
        app_version : 1.0
      app_developer : hgfeaon
    >>> httpd = make_server('', 8082, wsgi_app)
    >>> httpd.serve_forever()
    127.0.0.1 - - [12/Aug/2014 21:39:41] "GET / HTTP/1.1" 200 48
    ...
    

    这回make_server使用的WSGI处理函数(wsgi_app变量)就是paste模块通过loadapp函数读取配置文件载入进来的。

    实际上wsgi_app并不一定要是一个函数对象,它可以是一个实现了__call__方法的类实例,反正它是callable的就可以了,一般就把他们叫做application,简称app,所以一路上看到的都是app:main,loadapp这些。

  • 相关阅读:
    inflate用一个XML源填充view. LayoutInflater
    关于inflate的第3个参数
    关于inflate的第3个参数
    android ImageView scaleType属性
    android ImageView scaleType属性
    Android中设置文本颜色的三种方法
    JDK1.8与spring3.x的不兼容
    Spring整合activiti单元测试
    良好编程习惯的养成
    No output operations registered, so nothing to execute
  • 原文地址:https://www.cnblogs.com/lailailai/p/3908593.html
Copyright © 2011-2022 走看看