Car*_*ers 10 python twisted.web
这是我在使用Twisted.web时遇到的烦人问题.基本上,我有一个继承的类,twisted.web.resource.Resource并为Mako模板添加了一些默认的东西:
from twisted.web.resource import Resource
from mako.lookup import TemplateLookup
from project.session import SessionData
from project.security import make_nonce
class Page(Resource):
template = ""
def display(self, request, **kwargs):
session = SessionData(request.getSession())
if self.template:
templates = TemplateLookup(directories=['templates'])
template = templates.get_template(self.template)
return template.render(user=session.user,
info=session.info,
current_path=request.path,
nonce=make_nonce(session),
**kwargs)
else:
return ""
Run Code Online (Sandbox Code Playgroud)
然后,我把问题缩小到这个小类(我测试过),我写了一个继承自的资源Page:
class Test(pages.Page):
def render_GET(self, request):
return "<form method='post'><input type='submit'></form>"
def render_POST(self, request):
request.redirect("/test")
request.finish()
Run Code Online (Sandbox Code Playgroud)
我想要注意的是,在所有其他情况下,如果request.finish()不是函数中的最后一行,那么我会return紧接着它.
无论如何,我将这个类添加到站点中/test,当我在那里导航时,我得到一个提交按钮.我点击提交按钮,然后在控制台中我得到:
C:\Python26\lib\site-packages\twisted\web\server.py:200: UserWarning: Warning! request.finish called twice. self.finish()
但是,我第一次提交页面时才会收到此信息.每隔一段时间,这很好.我会忽略这一点,但它一直在唠叨我,我不能为我的生活找出它为什么这样做,以及为什么只有第一次提交页面.我似乎无法在网上找到任何东西,甚至在request.finish()代码中删除打印语句和回溯也没有透露任何信息.
今天早上我尝试request.finish()在资源中添加第二行,它仍然只给了我一次错误.我想它只会在一次资源中警告它 - 也许每次运行程序,或者每次会话,我不确定.在任何情况下,我都将其更改为:
class Test(pages.Page):
def render_GET(self, request):
return "<form method='post'><input type='submit'></form>"
def render_POST(self, request):
request.redirect("/test")
request.finish()
request.finish()
Run Code Online (Sandbox Code Playgroud)
只有两次消息,一次.我仍然不知道为什么我不能重新定向请求而不说它我完成了两次(因为我不能没有重定向request.finish()).
Car*_*ers 10
它一定要是:
request.redirect("/test")
request.finish()
return twisted.web.server.NOT_DONE_YET
Run Code Online (Sandbox Code Playgroud)
我决定对一些Twisted源代码进行筛选.我首先添加了一个回溯到打印错误的区域,如果request.finish()被调用两次:
def finish(self):
import traceback #here
"""
Indicate that all response data has been written to this L{Request}.
"""
if self._disconnected:
raise RuntimeError(
"Request.finish called on a request after its connection was lost; "
"use Request.notifyFinish to keep track of this.")
if self.finished:
warnings.warn("Warning! request.finish called twice.", stacklevel=2)
traceback.print_stack() #here
return
#....
Run Code Online (Sandbox Code Playgroud)
...
File "C:\Python26\lib\site-packages\twisted\web\server.py", line 200, in render
self.finish()
File "C:\Python26\lib\site-packages\twisted\web\http.py", line 904, in finish
traceback.print_stack()
我走进去,签出render在twisted.web.server发现这一点:
if body == NOT_DONE_YET:
return
if type(body) is not types.StringType:
body = resource.ErrorPage(
http.INTERNAL_SERVER_ERROR,
"Request did not return a string",
"Request: " + html.PRE(reflect.safe_repr(self)) + "<br />" +
"Resource: " + html.PRE(reflect.safe_repr(resrc)) + "<br />" +
"Value: " + html.PRE(reflect.safe_repr(body))).render(self)
if self.method == "HEAD":
if len(body) > 0:
# This is a Bad Thing (RFC 2616, 9.4)
log.msg("Warning: HEAD request %s for resource %s is"
" returning a message body."
" I think I'll eat it."
% (self, resrc))
self.setHeader('content-length', str(len(body)))
self.write('')
else:
self.setHeader('content-length', str(len(body)))
self.write(body)
self.finish()
Run Code Online (Sandbox Code Playgroud)
body是渲染资源的结果,所以一旦body填充,在我的问题中给出的示例情况下,finish已经在此请求对象上调用(因为self从此方法传递到资源的render方法).
通过查看此代码,很明显,通过返回,NOT_DONE_YET我会避免警告.
我本可以将该方法的最后一行更改为:
if not self.finished:
self.finish()
Run Code Online (Sandbox Code Playgroud)
但是,为了不修改图书馆,简短的答案是:
打电话后request.redirect()你必须打电话request.finish()然后return twisted.web.server.NOT_DONE_YET
我找到了一些关于此的文档.它与重定向请求无关,而是使用相关的呈现资源request.write().它说打电话request.finish()然后回来NOT_DONE_YET.从查看代码render()我可以看出为什么会这样.
| 归档时间: |
|
| 查看次数: |
4450 次 |
| 最近记录: |