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__.py

E:\DECODE-DJANGO\DJANGO-1.5.1\DJANGO\CORE\SERVERS
basehttp.py 重写 ServerHandler,WSGIServer,WSGIRequestHandler,定义 run() 函数
fastcgi.py
__init__.py

E:\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

http://daoluan.net

 

提前预知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

Django 中的 WSGI的更多相关文章

  1. Django 源码小剖: Django 中的 WSGI

    Django 其内部已经自带了一个方便本地测试的小服务器, 所以在刚开始学习 Django 的时候并不需搭建 apache 或者 nginx 服务器. Django 自带的服务器基于 python w ...

  2. Django中请求的生命周期

    1. 概述 首先我们知道HTTP请求及服务端响应中传输的所有数据都是字符串. 在Django中,当我们访问一个的url时,会通过路由匹配进入相应的html网页中. Django的请求生命周期是指当用户 ...

  3. Django中请求的生命周期 和 FBV模式和CBV模式

    Django的生命周期就是你的 一个请求所发生的整个流程 Django的生命周期内到底发生了什么呢?? . 当用户在浏览器中输入url时,浏览器会生成请求头和请求体发给服务端 请求头和请求体中会包含浏 ...

  4. Django 中url补充以及模板继承

    Django中的URL补充 默认值 在url写路由关系的时候可以传递默认参数,如下: url(r'^index/', views.index,{"name":"root& ...

  5. Django中的信号

    信号 Django 提供一个“信号分发器”,允许解耦的应用在框架的其它地方发生操作时会被通知到. 简单来说,信号允许特定的sender通知一组receiver某些操作已经发生. 这在多处代码和同一事件 ...

  6. Django中各目录文件的作用

    一般的项目结构如下(大同小异) my_site是一个项目,blog是项目下的应用之一,可以使用创建命令创建更多的应用. 最上层的django文件夹: 自己手动创建,名字随意. 第二层my_site文件 ...

  7. Django中使用Celery

    一.前言 Celery是一个基于python开发的分布式任务队列,如果不了解请阅读笔者上一篇博文Celery入门与进阶,而做python WEB开发最为流行的框架莫属Django,但是Django的请 ...

  8. web 架构 /http协议,状态码,django中常用命令

    什么是web应用? web应用 架构 :B/S架构 | C/S架构 网站:BS架构其实就是应用程序: B是浏览器 S是sever(实现了wsgi协议,实现了socket的服务端) + applicat ...

  9. Django中的Project和App的区别

    Django是一个非常流行的用python编写的Web框架,在使用Django之前,我们需要了解一些基本的概念,这样可以在使用Django的时候对其有一个更加深入的把握.本文主要介绍Django中两个 ...

随机推荐

  1. 汉字转整数,比系统简单易用!a2iLxx (覆盖物 16十六进制,VC6亲测可用)请提供意见~

    #include "string.h" #define INVALID_VALUE_LXX ((1 << (8 * sizeof(int) -1)) - 1) /*有符 ...

  2. 【Head First Javascript】学习笔记0——自己制作chm参考手册素材

    变量声明:var 常量声明:const 数据格式转换: 1.转换函数 parseInt(A):把字符串A转换成整数:其中A为只包含数字的字符串 parseFloat(A):把字符串A转换成浮点数:其中 ...

  3. Codeforces 328B-Sheldon and Ice Pieces(馋)

    B. Sheldon and Ice Pieces time limit per test 1 second memory limit per test 256 megabytes input sta ...

  4. The Swift Programming Language-官方教程精译Swift(4)字符串和字符

    String 是一个有序的字符集合,例如 "hello, world", "albatross".Swift 字符串通过 String 类型来表示,也可以表示为 ...

  5. VS2010类模板修改——添加版权、说明

    VS2010类模板修改——添加版权.说明 最近在学习使用Memcache,就想着用C#代码写一个实现Cache与Memcache以及将来若是能融入Redis切换使用的程序集...不过刚开始写代码,强迫 ...

  6. CentOs Linux 文件位置标记

    vsFTP默认位置: 匿名:/var/ftp/ 用户:/home/用户名 配置文件:/etc/vsftpd/ (一般安装软件后都会在/etc/下生成一个软件相关的配置文件夹) 防火墙位置: /etc/ ...

  7. Asp.Net MVC4 + Oracle + EasyUI + Bootstrap

    Asp.Net MVC4 + Oracle + EasyUI + Bootstrap --操作数据和验证 本文链接:http://www.cnblogs.com/likeli/p/4234238.ht ...

  8. 我的MYSQL学习心得(十三)

    原文:我的MYSQL学习心得(十三) 我的MYSQL学习心得(十三) 我的MYSQL学习心得(一) 我的MYSQL学习心得(二) 我的MYSQL学习心得(三) 我的MYSQL学习心得(四) 我的MYS ...

  9. ORA-00265: instance recovery required, cannot set ARCHIVELOG mode

    症状: 我打开后归档命令报告运行错误ORA-00265 SQL> alter database archivelog; alter database archivelog * ERROR at ...

  10. Android多媒体-MediaRecorder 录制音视频

    不多说,直接上代码,有具体凝视 MyAudioRecord.java import java.io.File; import java.io.IOException; import android.a ...