web.py源码分析: 模板(3)
admin
2023-07-31 00:45:44
0

前两篇文章主要说明了web.py的模板系统将模板文件处理后得到的结果:__template__()函数。本文主要讲述模板文件是如何变成__template__()函数的。

Render和frender

一般来说,更常用的是Render类,该类会处理整个目录下的模板,还支持缓存和嵌套模板。不过这些其实都和模板本身的解析基本没关系,以后再说明这个类的实现和用途。这里我们使用frender()函数:

12345 def frender(path, **keywords):    \”\”\”Creates a template from the given file path.    \”\”\”    return Template(open(path).read(), filename=path, **keywords) 

这个函数相当简单,只作了一键事情,就是读取模板文件内容,然后交给Template类处理,并且返回一个Template类实例。从这里也可以看出,整个模板的解析,只和Template类有关,frender是来打杂的。

Template类

Template实例的效果

当我们根据一个模板内容创建一个Template类实例t后,我们可以调用该实例,这相当于调用模板对应的__template__()函数,得到的结果是一个TemplateResult实例。

1234567891011121314151617 In [7]: t = web.template.frender(\”templates/hello.html\”)# coding: utf-8def __template__ (name):    __lineoffset__ = 4    loop = ForLoop()    self = TemplateResult(); extend_ = self.extend    extend_([u\’hello, \’, escape_(name, True), u\’\\n\’])     return self In [8]: print t(\”xxxx\”)hello, xxxx  In [9]: print type(t(\”xxxx\”)) <class \’web.template.TemplateResult\’>

Template实例化过程

Template实例化过程是把模板转换成HTML内容的实质性步骤,不过这个过程比较复杂。但是,概括的来讲,这个过程和Template的__init__()函数中的步骤差不都差不多。

1234567891011121314151617 # Template类的__init__()函数def __init__(self, text, filename=\’\’, filter=None, globals=None, builtins=None, extensions=None):    self.extensions = extensions or []    text = Template.normalize_text(text)    code = self.compile_template(text, filename)     _, ext = os.path.splitext(filename)    filter = filter or self.FILTERS.get(ext, None)    self.content_type = self.CONTENT_TYPES.get(ext, None)     if globals is None:        globals = self.globals    if builtins is None:        builtins = TEMPLATE_BUILTINS     BaseTemplate.__init__(self, code=code, filename=filename, filter=filter, globals=globals, builtins=builtins) 

首先把,参数里除了text以外的参数忽略掉,然后来看下对text的处理过程(text就是模板的内容)。整个过程概括的说有如下步骤:

  • 对text作归一化处理:text = Template.normalize_text(text), 主要换行符统一成n,删除BOM字符串,将$替换成$$,这个就是简单的字符串处理。
  • 编译模板得到编译后的Python字节码codecode = self.compile_template(text, filename),code就是之前已经提到过的__template__()函数。
  • 调用父类(BaseTemplate)的__init__()函数:创建__template__()函数的执行环境,并且实现可调用功能。

其他没有说明的代码,暂时都可以忽略,不会影响你理解Template的实例化过程。从上面的步骤可以看出,Template实例化的过程主要有两个:生成__template__()函数的代码并编译,以及创建__template__()函数的执行环境。

生成__template__()函数的代码

这个是模板生成过程中最长最复杂的一段,会应用到Python的token分析功能以及动态编译功能。还记得第一篇里,我们搭建实验环境的时候,修改了web.py源码,在一个地方插入了一行打印语句么?没错,就是这个compile_template()函数,我们现在来看看它是如何生成__template__()函数的代码的。

12345678910111213 def compile_template(self, template_string, filename):    code = Template.generate_code(template_string, filename, parser=self.create_parser())late_string, filename, parser=self.create_parser())支持缓存和嵌套模板。不过这些其实都和模板本身的解析基本没关系,以后再说明这个类的实现和用途。这里我们使用frender()函数:

12345 def frender(path, **keywords):    \”\”\”Creates a template from the given file path.    \”\”\”    return Template(open(path).read(), filename=path, **keywords) 

这个函数相当简单,只作了一键事情,就是读取模板文件内容,然后交给Template类处理,并且返回一个Template类实例。从这里也可以看出,整个模板的解析,只和Template类有关,frender是来打杂的。

Template类

Template实例的效果

当我们根据一个模板内容创建一个Template类实例t后,我们可以调用该实例,这相当于调用模板对应的__template__()函数,得到的结果是一个TemplateResult实例。

1234567891011121314151617 In [7]: t = web.template.frender(\”templates/hello.html\”)# coding: utf-8def __template__ (name):    __lineoffset__ = 4    loop = ForLoop()    self = TemplateResult(); extend_ = self.extend    extend_([u\’hello, \’, escape_(name, True), u\’\\n\’])     return self In [8]: print t(\”xxxx\”)hello, xxxx  In [9]: print type(t(\”xxxx\”)) <class \’web.template.TemplateResult\’>

Template实例化过程

Template实例化过程是把模板转换成HTML内容的实质性步骤,不过这个过程比较复杂。但是,概括的来讲,这个过程和Template的__init__()函数中的步骤差不都差不多。

1234567891011121314151617 # Template类的__init__()函数def __init__(self, text, filename=\’\’, filter=None, globals=None, builtins=None, extensions=None):    self.extensions = extensions or []    text = Template.normalize_text(text)    code = self.compile_template(text, filename)     _, ext = os.path.splitext(filename)    filter = filter or self.FILTERS.get(ext, None)    self.content_type = self.CONTENT_TYPES.get(ext, None)     if globals is None:        globals = self.globals    if builtins is None:        builtins = TEMPLATE_BUILTINS     BaseTemplate.__init__(self, code=code, filename=filename, filter=filter, globals=globals, builtins=builtins) 

首先把,参数里除了text以外的参数忽略掉,然后来看下对text的处理过程(text就是模板的内容)。整个过程概括的说有如下步骤:

  • 对text作归一化处理:text = Template.normalize_text(text), 主要换行符统一成n,删除BOM字符串,将$替换成$$,这个就是简单的字符串处理。
  • 编译模板得到编译后的Python字节码codecode = self.compile_template(text, filename),code就是之前已经提到过的__template__()函数。
  • 调用父类(BaseTemplate)的__init__()函数:创建__template__()函数的执行环境,并且实现可调用功能。

其他没有说明的代码,暂时都可以忽略,不会影响你理解Template的实例化过程。从上面的步骤可以看出,Template实例化的过程主要有两个:生成__template__()函数的代码并编译,以及创建__template__()函数的执行环境。

生成__template__()函数的代码

这个是模板生成过程中最长最复杂的一段,会应用到Python的token分析功能以及动态编译功能。还记得第一篇里,我们搭建实验环境的时候,修改了web.py源码,在一个地方插入了一行打印语句么?没错,就是这个compile_template()函数,我们现在来看看它是如何生成__template__()函数的代码的。

12345678910111213 def compile_template(self, template_string, filename):    code = Template.generate_code(template_string,

相关内容

热门资讯

Mobi、epub格式电子书如... 在wps里全局设置里有一个文件关联,打开,勾选电子书文件选项就可以了。
500 行 Python 代码... 语法分析器描述了一个句子的语法结构,用来帮助其他的应用进行推理。自然语言引入了很多意外的歧义,以我们...
定时清理删除C:\Progra... C:\Program Files (x86)下面很多scoped_dir开头的文件夹 写个批处理 定...
scoped_dir32_70... 一台虚拟机C盘总是莫名奇妙的空间用完,导致很多软件没法再运行。经过仔细检查发现是C:\Program...
65536是2的几次方 计算2... 65536是2的16次方:65536=2⁶ 65536是256的2次方:65536=256 6553...
小程序支付时提示:appid和... [Q]小程序支付时提示:appid和mch_id不匹配 [A]小程序和微信支付没有进行关联,访问“小...
pycparser 是一个用... `pycparser` 是一个用 Python 编写的 C 语言解析器。它可以用来解析 C 代码并构...
微信小程序使用slider实现... 众所周知哈,微信小程序里面的音频播放是没有进度条的,但最近有个项目呢,客户要求音频要有进度条控制,所...
Apache Doris 2.... 亲爱的社区小伙伴们,我们很高兴地向大家宣布,Apache Doris 2.0.0 版本已于...
python清除字符串里非数字... 本文实例讲述了python清除字符串里非数字字符的方法。分享给大家供大家参考。具体如下: impor...