Django 中的 WSGI
Django 源码小剖: Django 中的 WSGI
2013-09-06 22:31 by 捣乱小子, 334 阅读, 0 评论, 收藏, 编辑
Django 其内部已经自带了一个方便本地测试的小服务器, 所以在刚开始学习 Django 的时候并不需搭建 apache 或者 nginx 服务器. Django 自带的服务器基于 python wsgiref 模块实现的, 其百分之七八十的代码都是 wsgiref 中的代码, 只重写了一部分, 所以 Django 自带的服务器测试写个 helloworld 就好了.
Django 内置服务器在 django.core.servers 和 django.core.handlers, 这两者共同来实现.先看看 django.core.servers. 下面是目录结构:
E:\DECODE-DJANGO\DJANGO-1.5.1\DJANGO\CORE\SERVERS
basehttp.py 重写 ServerHandler,WSGIServer,WSGIRequestHandler,定义 run() 函数
fastcgi.py
__init__.py
下面的代码足以说明「百分之七八十」:
1
2
3
4
5
|
class ServerHandler(simple_server.ServerHandler, object ): ... class WSGIServer(simple_server.WSGIServer, object ): ... class WSGIRequestHandler(simple_server.WSGIRequestHandler, object ): |
具体内部做了一些变更:
- 重写了 write 函数, 当传输数据过大的时候分段传输
- 多了一些异常处理
- 错误记录
都是无关痛痒, 不详细展开了.这里定义了一个很有意思的函数 run():
1
2
3
4
5
6
7
8
9
10
11
|
def run(addr, port, wsgi_handler, ipv6 = False , threading = False ): server_address = (addr, port) if threading: httpd_cls = type ( str ( 'WSGIServer' ), (socketserver.ThreadingMixIn, WSGIServer), {}) else : httpd_cls = WSGIServer httpd = httpd_cls(server_address, WSGIRequestHandler, ipv6 = ipv6) httpd.set_app(wsgi_handler) httpd.serve_forever() 永久运行 |
这和上一篇 if __name__ == '__main__': 中的代码效果类似, 实例化服务器类, 让它跑起来. 在 run() 函数中可以根据喜好配置:
add: 地址, 可传入 ip 地址, 一般是 127.0.0.1
port: 端口, 自定义端口
wsgi_handler: 上节提到的 application, 在 django.core.handlers 中定义
ipv6: 如果为 true, 会将协议地址族换成是 AF_INET6
threading: 如果为 true, 服务器会被强制成 type(str('WSGIServer'), (socketserver.ThreadingMixIn, WSGIServer), {})(这个我漏讲了, 但功能是这样), 能处理多线程处理请求.
所以, 调用这个函数可以让一个自定义服务器跑起来.
wsgi_handler 参数定义了 application, 而 application 必须是一个 start_response(status, response_headers, exc_info=None) 形式的函数或者定义了 __call__ 的类. 而 django.core.handlers 就用后一种方式实现了 application.
E:\DECODE-DJANGO\DJANGO-1.5.1\DJANGO\CORE\HANDLERS
base.py application 的基类 BaseHandler
wsgi.py 实现 WSGIHandler 类, 定义了 __call__, 这样就名正言顺的 WSGI 中的 application 了
__init__.py
事实上, 在 WSGI 中除了 application,server 外, 还有一个 middleware, 名曰中间件. 在上一篇中故意漏了, 因为没有涉及到.最后我疏离一下上边提到的类模块等等, 方便大家找源码, 整理如下:
C:\PYTHON27\LIB\WSGIREF
handlers.py 定义了 BaseHandler, SimpleHandler 类
headers.py
simple_server.py 定义了 ServerHandler, WSGIRequestHandler 类, demo_app(), make_server()
util.py
validate.py
__init__.pyE:\DECODE-DJANGO\DJANGO-1.5.1\DJANGO\CORE\SERVERS
basehttp.py 重写 ServerHandler,WSGIServer,WSGIRequestHandler,定义 run() 函数
fastcgi.py
__init__.pyE:\DECODE-DJANGO\DJANGO-1.5.1\DJANGO\CORE\HANDLERS
base.py application 的基类 BaseHandler
wsgi.py 实现 WSGIHandler 类, 定义了 __call__, 这样就名正言顺的 WSGI 中的 application 了
__init__.py
ps: 目录根据实际情况会不同, 看具体情况.我已经在 github 备份了 Django 源码的注释: Decode-Django, 有兴趣的童鞋 fork 吧.
捣乱 2013-9-6
提前预知java8
我们一直在期待着Java 8的新功能,虽然很大一部分是对Java 7的扩展,发布时间也一推再推(原定9月发行,Java 8已经推迟到明年3月,本是要争取时间让安全修复主要针对客户端Java(JavaFX /swing))。但如今甲骨文终于承诺:新版本将是彻底的变革而不仅仅是Java 7的扩展。那Java 8到底是什么样的呢?
java8在试图”创新“,其实就是像腾讯一样,把别人的东西拿过来包装一样,看来腾讯在这方面走在前沿了。正如java社区讨论那样,java8增加了Lambda, streams, functional interfaces、java time 。。还有其他各种各样的东西,但是最主要的还是Lambda, streams, functional interfaces。下面一个一个的挨着介绍吧。
一、Lambda expressions
大家都熟知的Lambda 表达式终于出现在java8的api里面, 我觉得这对程序猿来说是一个巨大的好处,因为lambda表达式的出现让代码越来越简单。当我们JVM在编译lambda表达式的时候会把lambda表达式翻译成为功能接口(functional interface)。下面看看一个实例吧。
①、以前的老方法中没有使用lambda
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
System.out.println(“Action Detected”);
}
});
②、java8中使用lambda表达
button.addActionListener(e -> {
System.out.println(“Action Detected”);
});
通过上面的两个例子是不是感觉使用了lambda表达式比原来简单的多了,如果你还不明白的话,那么我在举一个例子,我相信这个例子大家应该很熟悉了吧 ,建立一个线程。
①、没有使用lambda表达式
//使用以前的方法创建线程
Runnable runnable1 = new Runnable() { @Override
public void run() {
System.out.println("Running without Lambda");
}
};
②、使用了lambda表达式
Runnable runnable2 = () -> {
System.out.println("Running from Lambda");
}
正如您看到的,使用Lambda表达式通常会使代码更容易阅读,需要更少的代码。但是Scala社区是怀疑的(详情请点击scala社区),他们认为java增加的功能有可能取代scala语言(主要是“=》”和“->”操作符),Java 8的语法已经很详细了但是和Scala比起来没有那么的清晰。一方面,如果Java继续发展和实现周围的一切像Scala已经做过的事(这也说明java也有‘抄袭’的可能),那么有可能不需要Scala。另一方面,如果它独自只提供核心功能,如帮助匿名内部类,然后Scala和其他语言将继续繁荣。这是最好的结果,它将允许其他语言继续生长和创造力而不用担心他们是否会变得过时。
二、streams
流,在这里的流不是所谓说的io操作中的InputStream和
OutputStream是在集合包里面增加了一个steams的集合。所以大家不要混淆了。既然它出现在java8中,肯定这个出现是有需求的,而且是必然的。
流并不是为了取代ArrayLists或其他集合。他们只是为了使操纵数据更容易和更快。一个流是一次使用对象。一旦它被遍历那么它就不能在被遍历(是一次使用对象)。streams可以被过滤(filter),也可以被遍历。streams包大约分两种顺序流(sequential stream)和平行流(parallel stream)。两种方式使得streams在多核处理器中扮演了一个重要角色,它使用fork / join并行性来分离工作,加快处理。
①、使用sequential stream:
List <Person> people=list.getStream.collect(Collectors.toList());
②、使用parallel stream
List <Person> people = list.getStream.parallel().collect(Collectors.toList());
说明:当我们遍历sequential stream的时候流中的每一项阅读处理,然后下一项是阅读(也就是读一点输出一点的意思)当遍历parallel stream的是时候,该数组被分成多个部分,每一个都是在一个不同的线程分别处理。结果然后放回一起输出。
遍历Parallel stream的过程
List originalList = someData; split1 = originalList(0, mid); split2 = originalList(mid,end); new Runnable(split1.process()); new Runnable(split2.process()); List revisedList = split1 + split2;
这个非常简单的示例说明了如何处理平行流。这就是它如何利用多核处理器的。
因为一个流只能遍历一次,通常返回另一个流,使用一个终端方法来获得有用的结果,通常使用的终端方法有下面这些 sum()
, collect()
, toArray()。最后只要流终止,但是这个结果是不可行的(至于为什么我相信大家仔细相信就明白了,我在这里就不用说了吧)。请看下面这个例子
Double result = list.getStream().mapToDouble(f -> f.getAmount()).sum(); List<Person> people = list.getStream().filter(f -> f.getAge() > 21).collect(Collectors.toList());
这个功能的最大的好处是能够使用多个处理器核心收集处理。而不是做传统的for循环,使用流在平行模式——理论上,平行模式的速度是每个核心速度之和。
三、功能接口(Functional interfaces)
Java 8将有一个新功能叫做功能接口。基本上,默认的方法都添加了这个接口,但是这个方法不需要写功能接口的实现(这个具体还有待研究,以java8具体出来为准)。这些方法可以直接从接口之中运行。
这样做是为了向后兼容为你的接口。举一个很简单的例子就是让流放入一个接口而无需改变所有的类来实现新方法。基本上,创建一个默认的方法的接口,所有的实现接口的类可以使用流。如果默认的方法是不正确的实现,它可以覆盖在实现它。这本质上是允许的形式做多重继承。这成为实现者的问题,因为实现者需要重写该方法,无论如何。实现者都可以选择使用哪些方法,但这意味着大量的类,实现接口仍然可以被改变。(有点像继承里面的构造方法一样,继承的类可以从写构造方法)
大多数人很熟悉Java。也许不会熟悉java的同胞兄弟Scala。细细比较java8和scala,java8的概念特征基本在Scala中都可以找到,尽管这个概念并不局限于Scala。然而,有一些差异:Java 8功能接口不能得到一个实现类的引用。Scala允许这与self关键字。语言书呆子会说,Java 8的功能性接口允许多重继承的行为,但Scala的特征是对于行为和状态都可以多重继承的。
其实java8还有很多东西比如说Accumulators,TLS SNI,HashMap
fixes就等着下次在介绍了,这次很晚了,程序猿们洗洗睡吧。
Django 中的 WSGI的更多相关文章
- Django 源码小剖: Django 中的 WSGI
Django 其内部已经自带了一个方便本地测试的小服务器, 所以在刚开始学习 Django 的时候并不需搭建 apache 或者 nginx 服务器. Django 自带的服务器基于 python w ...
- Django中请求的生命周期
1. 概述 首先我们知道HTTP请求及服务端响应中传输的所有数据都是字符串. 在Django中,当我们访问一个的url时,会通过路由匹配进入相应的html网页中. Django的请求生命周期是指当用户 ...
- Django中请求的生命周期 和 FBV模式和CBV模式
Django的生命周期就是你的 一个请求所发生的整个流程 Django的生命周期内到底发生了什么呢?? . 当用户在浏览器中输入url时,浏览器会生成请求头和请求体发给服务端 请求头和请求体中会包含浏 ...
- Django 中url补充以及模板继承
Django中的URL补充 默认值 在url写路由关系的时候可以传递默认参数,如下: url(r'^index/', views.index,{"name":"root& ...
- Django中的信号
信号 Django 提供一个“信号分发器”,允许解耦的应用在框架的其它地方发生操作时会被通知到. 简单来说,信号允许特定的sender通知一组receiver某些操作已经发生. 这在多处代码和同一事件 ...
- Django中各目录文件的作用
一般的项目结构如下(大同小异) my_site是一个项目,blog是项目下的应用之一,可以使用创建命令创建更多的应用. 最上层的django文件夹: 自己手动创建,名字随意. 第二层my_site文件 ...
- Django中使用Celery
一.前言 Celery是一个基于python开发的分布式任务队列,如果不了解请阅读笔者上一篇博文Celery入门与进阶,而做python WEB开发最为流行的框架莫属Django,但是Django的请 ...
- web 架构 /http协议,状态码,django中常用命令
什么是web应用? web应用 架构 :B/S架构 | C/S架构 网站:BS架构其实就是应用程序: B是浏览器 S是sever(实现了wsgi协议,实现了socket的服务端) + applicat ...
- Django中的Project和App的区别
Django是一个非常流行的用python编写的Web框架,在使用Django之前,我们需要了解一些基本的概念,这样可以在使用Django的时候对其有一个更加深入的把握.本文主要介绍Django中两个 ...
随机推荐
- 【足迹C++primer】49、超载,变化,运营商
超载,变化,运营商 Conversion Operators 转换操作符 operator type() const Conversions to an array or a function typ ...
- jquery密码强度检测
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- java_OutOfMorryError 内存溢出(replaceAll)
最近在使用string类中的replaceAll函数时碰到这个错误,由于string长度比较长,文本文档9M多,可以增加jvm的内存大小解决. 下面是一篇对OutOfMorryError错误的一些处理 ...
- 通用Key-Value存储系统的存储管理策略解析
Key-Value存储作为NoSQL存储的一种常见方式,提供了比SQL数据库更好的可扩展性和读写性能. 比方当前开源最热门的Memcached和Redis:淘宝的Tair.腾讯的Cme ...
- exec 重定向
文件中常用的重定向: command > filename把把标准输出重定向到一个新文件中command >> filename 把把标准输出重定向到一个文件中 (追加)comman ...
- 08. 删除重复&海量数据
原文:08. 删除重复&海量数据 重复数据,通常有两种:一是完全重复的记录,也就是所有字段的值都一样:二是部分字段值重复的记录. 一. 删除完全重复的记录完全重复的数据,通常是由于没有设置主键 ...
- 访问Google神器,魔高一尺,道高一丈!
最近谷歌的IP被大范围的禁用了.身处一个连谷歌都用不了的过度的程序员,深感命运多舛.幸好,魔高一尺,道高一丈.下面是几种可以使用谷歌的方法. 方法一 1)在chrome浏览器中输入:chrome:// ...
- Android开发之Mediaplayer
Android提供了常见的音频.视频的编码.解码机制.借助于多媒体类MediaPlayer的支持,开发者能够非常方便在在应用中播放音频.视频.本篇博客主要解说在Android平台下怎样播放一个音频文件 ...
- 对JSON数组对象排序-有键相同的元素,分组数量不一致,可采用如下的JS进行循环表格输出
var now=eval(data.data); // now.sort(sortBy('bigIdOrder', true, parseInt)); var tab=""; va ...
- sax(用于处理XML事件驱动的推模型)解析例子
SAX解析 Java程序如下: import org.xml.sax.helpers.DefaultHandler; import javax.xml.parsers.SAXParser; impor ...