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 == 200 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(304) if (self._status_code in (204, 304) or (self._status_code >= 100 and self._status_code < 200)): 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)
原文:https://www.cnblogs.com/ssyfj/p/8608526.html
【说明】:本文章由站长整理发布,文章内容不代表本站观点,如文中有侵权行为,请与本站客服联系(QQ:254677821)!