摘要:uwsgi执行顺序:启动master进程,执行python脚本的公共代码(import同一层)。然后生成worker进程,uwsgi.post_fork_hook=init_functions,初始化生成work子进程。然后请求来临时,每个子进程执行application代码

配置文件ini:

[uwsgi]

socket=192.168.62.20:8001

http=192.168.62.20:8003

master=true

pythonpath=../

module=breapi

processes=12

listen=256

disable-logging=true

daemonize=uwsgi.log

pidfile=uwsgi.pid

vacuum=true

harakiri=5

buffer-size=36384

stats=127.0.0.1:1717

原文http://pythonpaste.org/do-it-yourself-framework.html,http://blog.xsudo.com/archives/530.html

一个用来diy的框架

什么是WSGI

wsgi是一个在web服务器和应用程序app之间统一的接口,这样来规范app和web server,说的简单一点就是规范的接受web请求(request),但是不仅如此

1 你在类似CGI环境里分发传递,意味着数据可以在登录用户安全传递

2 在类似CGI环境里传递更多的上下文信息,脚本名称和路径

3 你可以扩展自身的wsgi环境,并允许回调,扩展信息并插入python对象,任何你想添加的却不能在http头里添加的

wsgi不仅仅是在web和应用之间,可以用在交互的每个层面 ,这使得应用app变成lib库,可以很好的扩展和重用

写一个wsgi应用

我们来简单的写一个wsgi的应用

简短的一个摘要

1 一个简单的wsgi应用就是一个可调用的对象比如一个function,有两个参数environ 和 start_response

2 环境environment是一个字典,python的标准字典有一些传统的http参数比如REQUEST_METHOD和HTTP_POST

3 environment可以包含一些特别的键wsgi.input 像post请求里的输入流

4 start_response是一个返回客户端结果的方法,需要提供http的状态和headers

start_response 是一个接受两个必需的固定参数和一个可选参数的 callable 对象. 为便于说明, 我们把这三个参数分别命名为: status, response_headers, 和 exc_info, 当然你也可以给他们起其他名字. 应用程序必需使用固定参数调用 start_response (比如:

start_response(status,response_headers)) , 参数 status 是一个形如 “999 Message here” 的表示状态的字符串。而 response_headers 参数是一个描述 http 响应头的列表, 其中每一个元素都是像 (header_name,header_value) 这样的元组。可选的 exc_info 参数会在后面的 start_response() callable 和 错误处理 两节中进行描述,该参数只有在应用程序产生了错误并希望在浏览器上显示错误信息的时候才用得上。

5 最后应用返回一个含有迭代器的response(通常是一个字符串列表)

例子

1

2

3
def app(environ, start_response):

    start_response('200
OK', [('content-type', 'text/html')])

    return ['Hello
world!']

然后更简单的一个server来运行这个app

1

2

3
if __name__ == '__main__':

    from paste import httpserver

    httpserver.serve(app, host='127.0.0.1', port='8080')

这样就可以在本机用8080端口来请求他了

一个带有互动的例子

1

2

3

4

5

6

7

8

9

10
from paste.request import parse_formvars

def app(environ, start_response):

    fields = parse_formvars(environ)

    if environ['REQUEST_METHOD'] == 'POST':

        start_response('200
OK', [('content-type', 'text/html')])

        return ['Hello,
', fields['name'], '!']

    else:

        start_response('200
OK', [('content-type', 'text/html')])

        return ['<form
method="POST">Name: <input type="text" '

                'name="name"><input type="submit"></form>']

这些都很简单,我们需要更多的页面,测试还有运行环境

对象发布 Object publishing

一个典型的对象发布 转换 ‘/’ 为 ‘..’

/articles/view?id=5 转换为 root.articles.view(id=5)

我们必须启动相应的对象

1

2

3

4

5

6
class ObjectPublisher(object):

def __init__(self, root):

        self.root = root

def __call__(self, environ, start_response):

        ...

app = ObjectPublisher(my_root_object)

我们重写__call__方法来实现一个callable ObjectPublisher ,就像一个wsgi的方法,现在我们要做的事情就是传递environ进去,调用它,然后返回结果response

路径

WSGI会把请求的路径放到两个变量SCRIPT_NAME和PATH_INFO里

SCRIPT_NAME就是我们将要到达的地方脚本名称,PATH_INFO就是请求的路径,这是框架寻找对象的方式

我们来实现__call__方法

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
def __call__(self, environ, start_response):

    fields = parse_formvars(environ)

    obj = self.find_object(self.root, environ)

    response_body = obj(**fields.mixed())

    start_response('200
OK', [('content-type', 'text/html')])

    return [response_body]

def find_object(self, obj, environ):

    path_info = environ.get('PATH_INFO', '')

    if not path_info or path_info == '/':

        # We've arrived!

        return obj

    # PATH_INFO always starts with a /, so we'll get rid of it:

    path_info = path_info.lstrip('/')

    # Then split the path into the "next" chunk, and everything

    # after it ("rest"):

    parts = path_info.split('/', 1)

    next = parts[0]

    if len(parts) == 1:

        rest = ''

    else:

        rest = '/' +
parts[1]

    # Hide private methods/attributes:

    assert not next.startswith('_')

    # Now we get the attribute; getattr(a, 'b') is equivalent

    # to a.b...

    next_obj = getattr(obj, next)

    # Now fix up SCRIPT_NAME and PATH_INFO...

    environ['SCRIPT_NAME'] += '/' +
next

    environ['PATH_INFO'] = rest

    # and now parse the remaining part of the URL...

    return self.find_object(next_obj, environ)

现在用ObjectPublisher来包装应用,并放到一个包中去

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16
from objectpub import ObjectPublisher

class Root(object):

# The "index" method:

    def __call__(self):

        return '''

        <form action="welcome">

        Name: <input type="text" name="name">

        <input type="submit">

        </form>

        '''

def welcome(self, name):

        return 'Hello
%s!' % name

app = ObjectPublisher(Root())

if __name__ == '__main__':

    from paste import httpserver

    httpserver.serve(app, host='127.0.0.1', port='8080')

需要注意的是,本来WSGI是要传入一个app的方法的,于是这里用了对象,并实现了__call__方法,结果是一样的

我们会发现缺少很多东西,比较特殊的我们没有地方去设置输出的headers,还有request里的信息是很少的

1

2

3

4

5

6

7

8

9

10

11
# This is just a dictionary-like object that has case-

# insensitive keys:

from paste.response import HeaderDict

class Request(object):

    def __init__(self, environ):

        self.environ = environ

        self.fields = parse_formvars(environ)

class Response(object):

    def __init__(self):

        self.headers = HeaderDict(

            {'content-type': 'text/html'})

我们不想改变方法,但是不能让request对象和response对象在全局的变量里,因为我们想要线程安全

修改__call__方法为

1

2

3

4

5

6

7

8

9

10

11
import threading

webinfo = threading.local()

class ObjectPublisher(object):

    ...

def __call__(self, environ, start_response):

        webinfo.request = Request(environ)

        webinfo.response = Response()

        obj = self.find_object(self.root, environ)

        response_body = obj(**dict(webinfo.request.fields))

        start_response('200
OK', webinfo.response.headers.items())

        return [response_body]

现在在我们的方法里可以这么做

1

2

3
class Root:

    def rss(self):

        webinfo.response.headers['content-type'] = 'text/xml'



一个UWSGI的例子的更多相关文章

  1. 用一个简单的例子来理解python高阶函数

    ============================ 用一个简单的例子来理解python高阶函数 ============================ 最近在用mailx发送邮件, 写法大致如 ...

  2. Spring-Context之一:一个简单的例子

    很久之前就想系统的学习和掌握Spring框架,但是拖了很久都没有行动.现在趁着在外出差杂事不多,就花时间来由浅入深的研究下Spring框架.Spring框架这几年来已经发展成为一个巨无霸产品.从最初的 ...

  3. 高仿“点触验证码”做的一个静态Html例子

    先上源码: <html> <head> <title>TouClick - Designed By MrChu</title> <meta htt ...

  4. 关于apriori算法的一个简单的例子

    apriori算法是关联规则挖掘中很基础也很经典的一个算法,我认为很多教程出现大堆的公式不是很适合一个初学者理解.因此,本文列举一个简单的例子来演示下apriori算法的整个步骤. 下面这个表格是代表 ...

  5. 扩展Python模块系列(二)----一个简单的例子

    本节使用一个简单的例子引出Python C/C++ API的详细使用方法.针对的是CPython的解释器. 目标:创建一个Python内建模块test,提供一个功能函数distance, 计算空间中两 ...

  6. fitnesse - 一个简单的例子(slim)

    fitnesse - 一个简单的例子(slim) 2017-09-30 目录1 编写测试代码(Fixture code)2 编写wiki page并运行  2.1 新建wikiPage  2.2 运行 ...

  7. Struts2的配置和一个简单的例子

    Struts2的配置和一个简单的例子 笔记仓库:https://github.com/nnngu/LearningNotes 简介 这篇文章主要讲如何在 IntelliJ IDEA 中使用 Strut ...

  8. 一个简单的例子搞懂ES6之Promise

    ES5中实现异步的常见方式不外乎以下几种: 1. 回调函数 2. 事件驱动 2. 自定义事件(根本上原理同事件驱动相同) 而ES6中的Promise的出现就使得异步变得非常简单.promise中的异步 ...

  9. 一个简单的例子了解states

    在大规模的配置管理工作中,我们要编写大量的states.sls文件.top.sls是states系统的入口文件,它负责指定哪些设备调用哪些states.sls文件.statse的默认工作目录是在/sr ...

随机推荐

  1. vb6学习心路

    1.不能加载 'MSCOMCTL.OCX'--继续加载工程吗解决办法:新建一个VB工程,然后按CTRL + T,选中 “Microsoft Windows Common Controls 6.0” 然 ...

  2. UVA 11992 线段树

    input r c m      r<=20,1<=m<=20000 m行操作 1 x1 y1 x2 y2 v       add v 2 x1 y1 x2 y2 v       s ...

  3. webservice(soap)接口的加密,SHA-1实现

    import java.io.UnsupportedEncodingException;import java.security.MessageDigest;import java.security. ...

  4. java数据结构之有序表查找

    这篇文章是关于有序表的查找,主要包括了顺序查找的优化用法.折半查找.插值查找.斐波那契查找: 顺序优化查找:效率极为底下,但是算法简单,适用于小型数据查找: 折半查找:又称为二分查找,它是从查找表的中 ...

  5. [转]理解SSL(https)中的对称加密与非对称加密

    加密 解密 Tweet   密码学最早可以追溯到古希腊罗马时代,那时的加密方法很简单:替换字母. 早期的密码学 古希腊人用一种叫 Scytale 的工具加密.更快的工具是 transposition ...

  6. AutoTile 自动拼接(一) 学习与实践

    恩,大家好,这两天江苏冷空气袭击,下了今年 第一场第二场雪. 不过今天我要说的 ,和 上面的 屁关系都没有. 今天要说的是 2d无缝自动拼接.大家有没有玩过  RPG Maker VX Ace. 类似 ...

  7. http://www.iteye.com/job/topic/1133159

    Lucene 的索引体系是一个写独占,读共享的结构,这意味着,我们在使用多线程进行添加索引时,性能并不会得到明显的提升,所以任何时刻只能有一个线程对索引进行写 入操作,而保障这个操作的安全性则是来自于 ...

  8. HDU 4738 Caocao's Bridges(割边)

    乍一看一个模板题,仔细一看还是模板题,但是三个坑.1,不是连通图,放0个.2 守卫为0,放1个. 3注意重边. #include<iostream> #include<cstdio& ...

  9. js 基础对象二

    大的分类 JavaScript 对象 JS Array JS Boolean JS Date JS Math JS Number JS String JS RegExp JS Functions JS ...

  10. Git学习 -- 标签管理

    新建标签 git tag <tagname>   默认为HEAD,也可以指定一个commit id eg.   git tag v0.9  git tag v1.0 31aa59c git ...