• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • vbs
  • DOS/BAT
  • hta/htc
  • python
  • perl
  • VBA
  • ColdFusion
  • ruby
  • PowerShell
  • Lua
  • Golang
  • linux shell
您的位置:首页 > 脚本语言 >python > 详细解读Python的web.py框架下的application.py模块

详细解读Python的web.py框架下的application.py模块

作者: 字体:[增加 减小] 来源:互联网

通过本文主要向大家介绍了python3 web.py,python web.py,python 安装web.py,python web2py,python web.py下载等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

本文主要分析的是web.py库的application.py这个模块中的代码。总的来说,这个模块主要实现了WSGI兼容的接口,以便应用程序能够被WSGI应用服务器调用。WSGI是Web Server Gateway Interface的缩写,具体细节可以查看WSGI的WIKI页面
接口的使用
使用web.py自带的HTTP Server

下面这个例子来自官方文档的Hello World,这个代码一般是应用入口的代码:

import web

urls = ("/.*", "hello")
app = web.application(urls, globals())

class hello:
  def GET(self):
    return 'Hello, world!'

if __name__ == "__main__":
  app.run()

</div>

上面的例子描述了一个web.py应用最基本的组成元素:

  •     URL路由表
  •     一个web.application实例app
  •     调用app.run()

其中,app.run()的调用是初始化各种WCGI接口,并启动一个内置的HTTP服务器和这些接口对接,代码如下:

def run(self, *middleware):
  return wsgi.runwsgi(self.wsgifunc(*middleware))

</div>

与WSGI应用服务器对接

如果你的应用要与WSGI应用服务器对接,比如uWSGI,gunicorn等,那么应用入口的代码就要换一种写法了:

import web

class hello:
  def GET(self):
    return 'Hello, world!'

urls = ("/.*", "hello")
app = web.application(urls, globals())
application = app.wsgifunc()

</div>

在这种场景下,应用的代码不需要启动HTTP服务器,而是实现一个WSGI兼容的接口供WSGI服务器调用。web.py框架为我们实现了这样的接口,你只需要调用application = app.wsgifunc()就可以了,这里所得到的application变量就是WSGI接口(后面分析完代码你就会知道了)。
WSGI接口的实现分析

分析主要围绕着下面两行代码进行:

app = web.application(urls, globals())
application = app.wsgifunc()

</div>

web.application实例化

初始化这个实例需要传递两个参数:URL路由元组和globals()的结果。

另外,还可以传递第三个变量:autoreload,用来指定是否需要自动重新导入Python模块,这在调试的时候很有用,不过我们分析主要过程的时候可以忽略。

application类的初始化代码如下:

class application:
  def __init__(self, mapping=(), fvars={}, autoreload=None):
    if autoreload is None:
      autoreload = web.config.get('debug', False)
    self.init_mapping(mapping)
    self.fvars = fvars
    self.processors = []

    self.add_processor(loadhook(self._load))
    self.add_processor(unloadhook(self._unload))

    if autoreload:
      ...

</div>

其中,autoreload相关功能的代码略去了。其他的代码主要作了如下几个事情:

  •     self.init_mapping(mapping):初始化URL路由映射关系。
  •     self.add_processor():添加了两个处理器。

初始化URL路由映射关系

def init_mapping(self, mapping):
  self.mapping = list(utils.group(mapping, 2))

</div>

这个函数还调用了一个工具函数,效果是这样的:

urls = ("/", "Index",
    "/hello/(.*)", "Hello",
    "/world", "World")

</div>

如果用户初始化时传递的元组是这样的,那么调用init_mapping之后:

self.mapping = [["/", "Index"],
        ["/hello/(.*)", "Hello"],
        ["/world", "World"]]

</div>

后面框架在进行URL路由时,就会遍历这个列表。
添加处理器

  self.add_processor(loadhook(self._load))
  self.add_processor(unloadhook(self._unload))

</div>

这两行代码添加了两个处理器:self._load和self._unload,而且还对这两个函数进行了装饰。处理器的是用在HTTP请求处理前后的,它不是真正用来处理一个HTTP请求,但是可以用来作一些额外的工作,比如官方教程里面有提到的给子应用添加session的做法,就是使用了处理器:

def session_hook():
  web.ctx.session = session

app.add_processor(web.loadhook(session_hook))

</div>

处理器的定义和使用都是比较复杂的,后面专门讲。
wsgifunc函数

wsgifunc的执行结果是返回一个WSGI兼容的函数,并且该函数内部实现了URL路由等功能。

def wsgifunc(self, *middleware):
  """Returns a WSGI-compatible function for this application."""
  ...
  for m in middleware: 
    wsgi = m(wsgi)

  return wsgi

</div>

除开内部函数的定义,wsgifunc的定义就是这么简单,如果没有实现任何中间件,那么就是直接返回其内部定义的wsgi函数。
wsgi函数

该函数实现了WSGI兼容接口,同时也实现了URL路由等功能。

def wsgi(env, start_resp):
  # clear threadlocal to avoid inteference of previous requests
  self._cleanup()

  self.load(env)
  try:
    # allow uppercase methods only
    if web.ctx.method.upper() != web.ctx.method:
      raise web.nomethod()

    result = self.handle_with_processors()
    if is_generator(result):
      result = peep(result)
    else:
      result = [result]
  except web.HTTPError, e:
    result = [e.data]

  result = web.safestr(iter(result))

  status, headers = web.ctx.status, web.ctx.headers
  start_resp(status, headers)

  def cleanup():
    self._cleanup()
    yield '' # force this function to be a generator

  return itertools.chain(result, cleanup())

for m in middleware: 
  wsgi = m(wsgi)

return wsgi

</div>

下面来仔细分析一下这个函数:

  self._cleanup()
  self.load(env)

</div>

self._cleanup()内部调用utils.ThreadedDict.clear_all(),清除所有的thread local数据,避免内存泄露(因为web.py框架的很多数据都会保存在thread local变量中)。

self.load(env)使用env中的参数初始化web.ctx变量,这些变量涵盖了当前请求的信息,我们在应用中有可能会使用到,比如web.ctx.fullpath。

  try:
    # allow uppercase methods only
    if web.ctx.method.upper() != web.ctx.method:
      raise web.nomethod()

    result = self.handle_with_processors()
    if is_generator(result):
      result = peep(result)
    else:
      result = [result]
  except web.HTTPError, e:
    result = [e.data]

</div>

这一段主要是调用self.handle_with_processors(),这个函数会对请求的URL进行路由,找到合适的类或子应用来处理该请求,也会调用添加的处理器来做一些其他工作(关于处理器的部分,后面专门讲)。对于处理的返回结果,可能有三种方式:

  1.     返回一个可迭代对象,则进行安全迭代处理。
  2.     返回其他值,则创建一个列表对象来存放。
  3.     如果抛出了一个HTTPError异常(比如我们使用raise web.OK("hello, world")这种方式来返回结果时),则将异常中的数据e.data封装成一个列表。

-

  result = web.safestr(iter(result))

  status, headers = web.ctx.status, web.ctx.headers
  start_resp(status, headers)

  def cleanup():
    self._cleanup()
    yield '' # force this function to be a generator

  return itertools.chain(result, cleanup())

</div>

接下来的这段代码,会对前面返回的列表result进行字符串化处理,得到HTTP Response的body部分。然后根据WSGI的规范作如下两个事情:

  1.     调用start_resp函数。
  2.     将result结果转换成一个迭代器。

现在你可以看到,之前我们提到的application = app.wsgifunc()就是将wsgi函数赋值给application变量,这样应用服务器就可以采用WSGI标准和我们的应用对接了。
处理HTTP请求

前面分析的代码已经说明了web.py框架如何

您可能想查找下面的文章:

  • 详解python3实现的web端json通信协议
  • 详解python3实现的web端json通信协议
  • 浅析Python的web.py框架中url的设定方法
  • Python3控制路由器——使用requests重启极路由.py
  • Python3实现Web网页图片下载
  • 详细解读Python的web.py框架下的application.py模块
  • 详细解读Python的web.py框架下的application.py模块
  • 安装Python的web.py框架并从hello world开始编程
  • 安装Python的web.py框架并从hello world开始编程

相关文章

  • Python实现给文件添加内容及得到文件信息的方法
  • 解决Python中由于logging模块误用导致的内存泄露
  • python的几种开发工具介绍
  • python对指定目录下文件进行批量重命名的方法
  • 使用Python的web.py框架实现类似Django的ORM查询的教程
  • python通过zlib实现压缩与解压字符串的方法
  • python中私有函数调用方法解密
  • Python验证码识别的方法
  • 跟老齐学Python之集成开发环境(IDE)
  • 利用Python破解验证码实例详解

文章分类

  • vbs
  • DOS/BAT
  • hta/htc
  • python
  • perl
  • VBA
  • ColdFusion
  • ruby
  • PowerShell
  • Lua
  • Golang
  • linux shell

最近更新的内容

    • 浅谈Python中的闭包
    • Python根据区号生成手机号码的方法
    • python使用多线程不断刷新网页的方法
    • 用Python的Tornado框架结合memcached页面改善博客性能
    • Python的GUI框架PySide的安装配置教程
    • Python常用模块用法分析
    • 使用Python中的cookielib模拟登录网站
    • 利用Python生成文件md5校验值函数的方法
    • Python-基础-入门 简介
    • Python实现3行代码解简单的一元一次方程

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有