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. Scapy的使用

    0.前言 最近现场测试项目时,突如其来需要伪造IGMP报文,骗取交换机相关组播流量,慌忙之下学习了Scapy的使用,以及相关快速学习的方法,在这里分享下. 1.Scapy库安装 github地址:ht ...

  2. centos7编译安装zabbix(附带编译安装lnmp)

    先把防火墙和selinux关闭: sytemctl stop firewalld setenforce 0 1.yum安装依赖: yum -y install wget openssl* gcc gc ...

  3. 软件工程_9th weeks

    PSP DATE START_TIME END_TIME EVENT TYPE       TIME 4.30-5.3 5:30 4:00 旅游 娱乐       72h 5.3 14:00 17:0 ...

  4. 反编译微信小程序

    最近看了个微信小程序古诗词全集,想知道他的前后端是怎么实现的,所以就想到了反编译.小程序安装后会有个wxapkg格式的文件存在/data/data/com.tencent.mm/MicroMsg/** ...

  5. Ubuntu 16.04配置JDK

    此篇为http://www.cnblogs.com/EasonJim/p/7139275.html的分支页. 一.JRE和JDK JRE(Java Runtime Environment)是运行一个基 ...

  6. jenkins--svn+Email自动触发1(作业设置)

    项目名称设置: svn设置: 触发构建设置: 构建加入sonar-scanner代码扫描: 邮件设置: 邮件触发器配置:

  7. BZOJ4034[HAOI2015]树上操作——树链剖分+线段树

    题目描述 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中所有点的点权都 ...

  8. Android 屏幕操作

    1 全屏显示Activity 代码 : 方法一:编程实现 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, Window ...

  9. BZOJ 2929: [Poi1999]洞穴攀行

    2929: [Poi1999]洞穴攀行 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 351  Solved: 195[Submit][Status][ ...

  10. [luogu2149][bzoj1880][SDOI2009]Elaxia的路线【拓扑排序+最短路+DP】

    题目描述 最近,Elaxia和w的关系特别好,他们很想整天在一起,但是大学的学习太紧张了,他们 必须合理地安排两个人在一起的时间. Elaxia和w每天都要奔波于宿舍和实验室之间,他们 希望在节约时间 ...