1.初始代码:

def get(self, *args, **kwargs):
import time
tm = time.time()
self.render('home/index.html', time=tm)

2.代码追踪render:

    # 第一次执行get方法时,通过render方法已经生成了数据,具体存在地方,参见源码
def render(self, template_name, **kwargs):
"""Renders the template with the given arguments as the response."""
if self._finished:
raise RuntimeError("Cannot render() after finish()")
html = self.render_string(template_name, **kwargs) # Insert the additional JS and CSS added by the modules on the page
js_embed = []
js_files = []
css_embed = []
css_files = []
html_heads = []
html_bodies = []
for module in getattr(self, "_active_modules", {}).values():
embed_part = module.embedded_javascript()
if embed_part:
js_embed.append(utf8(embed_part))
file_part = module.javascript_files()
if file_part:
if isinstance(file_part, (unicode_type, bytes)):
js_files.append(file_part)
else:
js_files.extend(file_part)
embed_part = module.embedded_css()
if embed_part:
css_embed.append(utf8(embed_part))
file_part = module.css_files()
if file_part:
if isinstance(file_part, (unicode_type, bytes)):
css_files.append(file_part)
else:
css_files.extend(file_part)
head_part = module.html_head()
if head_part:
html_heads.append(utf8(head_part))
body_part = module.html_body()
if body_part:
html_bodies.append(utf8(body_part)) if js_files:
# Maintain order of JavaScript files given by modules
js = self.render_linked_js(js_files)
sloc = html.rindex(b'</body>')
html = html[:sloc] + utf8(js) + b'\n' + html[sloc:]
if js_embed:
js = self.render_embed_js(js_embed)
sloc = html.rindex(b'</body>')
html = html[:sloc] + js + b'\n' + html[sloc:]
if css_files:
css = self.render_linked_css(css_files)
hloc = html.index(b'</head>')
html = html[:hloc] + utf8(css) + b'\n' + html[hloc:]
if css_embed:
css = self.render_embed_css(css_embed)
hloc = html.index(b'</head>')
html = html[:hloc] + css + b'\n' + html[hloc:]
if html_heads:
hloc = html.index(b'</head>')
html = html[:hloc] + b''.join(html_heads) + b'\n' + html[hloc:]
if html_bodies:
hloc = html.index(b'</body>')
html = html[:hloc] + b''.join(html_bodies) + b'\n' + html[hloc:]
self.finish(html)

数据先是保存在html局部变量中,传入finish中作为参数处理

3.追踪finish代码:

    def finish(self, chunk=None):
"""Finishes this response, ending the HTTP request."""
if self._finished:
raise RuntimeError("finish() called twice") if chunk is not None:
self.write(chunk) # Automatically support ETags and add the Content-Length header if
# we have not flushed any content yet.
if not self._headers_written:
if (self._status_code == and
self.request.method in ("GET", "HEAD") and
"Etag" not in self._headers):
self.set_etag_header()
if self.check_etag_header():
self._write_buffer = []
self.set_status()
if (self._status_code in (, ) or
(self._status_code >= and self._status_code < )):
assert not self._write_buffer, "Cannot send body with %s" % self._status_code
self._clear_headers_for_304()
elif "Content-Length" not in self._headers:
content_length = sum(len(part) for part in self._write_buffer)
self.set_header("Content-Length", content_length) if hasattr(self.request, "connection"):
# Now that the request is finished, clear the callback we
# set on the HTTPConnection (which would otherwise prevent the
# garbage collection of the RequestHandler when there
# are keepalive connections)
self.request.connection.set_close_callback(None) self.flush(include_footers=True)
self.request.finish()
self._log()
self._finished = True
self.on_finish()
self._break_cycles()

数据chunk(即是传入的html变量)在write方法中又进行处理

4.追踪write方法:

    def write(self, chunk):
"""Writes the given chunk to the output buffer. To write the output to the network, use the flush() method below. If the given chunk is a dictionary, we write it as JSON and set
the Content-Type of the response to be ``application/json``.
(if you want to send JSON as a different ``Content-Type``, call
set_header *after* calling write()). Note that lists are not converted to JSON because of a potential
cross-site security vulnerability. All JSON output should be
wrapped in a dictionary. More details at
http://haacked.com/archive/2009/06/25/json-hijacking.aspx/ and
https://github.com/facebook/tornado/issues/1009
"""
if self._finished:
raise RuntimeError("Cannot write() after finish()")
if not isinstance(chunk, (bytes, unicode_type, dict)):
message = "write() only accepts bytes, unicode, and dict objects"
if isinstance(chunk, list):
message += ". Lists not accepted for security reasons; see " + \
"http://www.tornadoweb.org/en/stable/web.html#tornado.web.RequestHandler.write"
raise TypeError(message)
if isinstance(chunk, dict):
chunk = escape.json_encode(chunk)
self.set_header("Content-Type", "application/json; charset=UTF-8")
chunk = utf8(chunk)
self._write_buffer.append(chunk)

发现数据存放在类成员变量中_write_buffer

若是想在自定义函数中直接输出该数据,为空

def get(self, *args, **kwargs):
import time
tm = time.time()
self.render('home/index.html', time=tm)
print(self._write_buffer, len(self._write_buffer)) # 为空

因为在finish方法中蓝色部分函数flush中对于数据进行了下一步处理:

5.追踪flush方法(部分源码):

    但是在执行finish时,先要执行flush(部分源码)
def flush(self, include_footers=False, callback=None):
"""Flushes the current output buffer to the network. The ``callback`` argument, if given, can be used for flow control:
it will be run when all flushed data has been written to the socket.
Note that only one flush callback can be outstanding at a time;
if another flush occurs before the previous flush's callback
has been run, the previous callback will be discarded. .. versionchanged:: 4.0
Now returns a `.Future` if no callback is given.
"""
chunk = b"".join(self._write_buffer)
self._write_buffer = [] #将列表置为空

所以要想获取数据:需要进行其他处理,例如:

(1)修改源码,保存数据

(2)重写父类函数flush,将数据提前截取保存在新的变量中

为了尽量不修改源码,可以选择第二种方法

6.重写父类函数flush

class IndexHandler(tornado.web.RequestHandler):
def flush(self, include_footers=False, callback=None):
self._data_html = self._write_buffer
super(IndexHandler,self).flush(include_footers,callback)

将数据保存在自己定义的数据_data_html 中

使用时可以直接获取数据

    def get(self, *args, **kwargs):
import time
tm = time.time()
self.render('home/index.html',time=tm)
print(self._data_html)

python---redis缓存页面前戏之剖析render源码的更多相关文章

  1. Python 多线程、多进程 (一)之 源码执行流程、GIL

    Python 多线程.多进程 (一)之 源码执行流程.GIL Python 多线程.多进程 (二)之 多线程.同步.通信 Python 多线程.多进程 (三)之 线程进程对比.多线程 一.python ...

  2. Python3 Selenium WebDriver网页的前进、后退、刷新、最大化、获取窗口位置、设置窗口大小、获取页面title、获取网页源码、获取Url等基本操作

    Python3 Selenium WebDriver网页的前进.后退.刷新.最大化.获取窗口位置.设置窗口大小.获取页面title.获取网页源码.获取Url等基本操作 通过selenium webdr ...

  3. Selenium WebDriver-网页的前进、后退、刷新、最大化、获取窗口位置、设置窗口大小、获取页面title、获取网页源码、获取Url等基本操作

    通过selenium webdriver操作网页前进.后退.刷新.最大化.获取窗口位置.设置窗口大小.获取页面title.获取网页源码.获取Url等基本操作 from selenium import ...

  4. 硬核剖析ThreadLocal源码,面试官看了直呼内行

    工作面试中经常遇到ThreadLocal,但是很多同学并不了解ThreadLocal实现原理,到底为什么会发生内存泄漏也是一知半解?今天一灯带你深入剖析ThreadLocal源码,总结ThreadLo ...

  5. 一个Python开源项目-腾讯哈勃沙箱源码剖析(上)

    前言 2019年来了,2020年还会远吗? 请把下一年的年终奖发一下,谢谢... 回顾逝去的2018年,最大的改变是从一名学生变成了一位工作者,不敢说自己多么的职业化,但是正在努力往那个方向走. 以前 ...

  6. Spring mvc Data Redis—Pub/Sub(附Web项目源码)

    一.发布和订阅机制 当一个客户端通过 PUBLISH 命令向订阅者发送信息的时候,我们称这个客户端为发布者(publisher). 而当一个客户端使用 SUBSCRIBE 或者 PSUBSCRIBE ...

  7. Spring Data Redis—Pub/Sub(附Web项目源码)

    一.发布和订阅机制 当一个客户端通过 PUBLISH 命令向订阅者发送信息的时候,我们称这个客户端为发布者(publisher). 而当一个客户端使用 SUBSCRIBE 或者 PSUBSCRIBE ...

  8. Spring Data Redis—Pub/Sub(附Web项目源码) (转)

    一.发布和订阅机制 当一个客户端通过 PUBLISH 命令向订阅者发送信息的时候,我们称这个客户端为发布者(publisher). 而当一个客户端使用 SUBSCRIBE 或者 PSUBSCRIBE ...

  9. Python实现淘宝秒杀聚划算自动提醒源码

    快来加入群[python爬虫交流群](群号570070796),发现精彩内容. 本实例能够监控聚划算的抢购按钮,在聚划算整点聚的时间到达时发出提醒(音频文件自己定义位置)并自动弹开页面(URL自己定义 ...

随机推荐

  1. Python学习笔记(一)——初学Python

    1.Python环境配置 本人配置Python2.7及Python3.6版本 将Python3.6环境配置在线,因此默认为Python3.6版本 Python2.7及Python3.6共存 2.简单操 ...

  2. CSS里Postion几个取值relative、absolute、static、fixed的区别和用法

    ---恢复内容开始--- static:静态定位,也是postion的默认值,没有定位,元素出现在正常的流中,忽略top\bottom\left\right或者z-index声明. relative: ...

  3. 9-Python3从入门到实战—基础之条件控制语句

    Python从入门到实战系列--目录 条件判断 if 条件判断 if 语句语法 if <条件判断1>: <执行1> elif <条件判断2>: <执行2> ...

  4. window.setTimeout

    https://developer.mozilla.org/zh-CN/docs/Web/API/Window/setTimeout

  5. Apache的Thrift引发的编译思考

    最近偶然看到了Apache的Thrift,感觉有点像Corba架构后的变种(赞一个,Facebook真伟大).WSDL能生成C#和Java的(SOAP标准接口,做WebService都用过).Corb ...

  6. FreeMarker boolean Issue

    FreeMarker template error:Can't convert boolean to string automatically, because the "boolean_f ...

  7. 如何将数据库引擎配置为侦听多个 TCP 端口

    SQL Server 2005         为 SQL Server 启用 TCP/IP 后,数据库引擎将侦听连接点上是否有传入的连接(由 IP 地址和 TCP 端口号组成).下列步骤将创建一个表 ...

  8. [转载]Memory Limits for Windows and Windows Server Releases

    Memory Limits for Windows and Windows Server Releases This topic describes the memory limits for sup ...

  9. (String)强制转换、toString()和String.valueOf()的区别

    String:毫无疑问,这种就是强转形式,简单方便,效率高.java程序员可能看到效率高或许有些激动,但是它有他的不好,那就是局限性.在java的世界里没有什么东西是没有缺点的,总有一些好的方面同时也 ...

  10. jmeter作用域规则

    创建测试计划时,会创建一个有序的一系列将要被执行的请求列表,这些请求通常被组织在有序的控制器下 一些控制器会影响包含在它下面的请求顺序 ,这些特殊的控制器可以参考这里:the component re ...