TwistedPython-延迟';s回调&x27;s函数调用,引发的异常未显示在标准输出中
测试设置 我有一个异步Twisted HTTP服务器用于处理POST:TwistedPython-延迟';s回调&x27;s函数调用,引发的异常未显示在标准输出中,python,exception,twisted,Python,Exception,Twisted,测试设置 我有一个异步Twisted HTTP服务器用于处理POST: class HttpResource(Resource): isLeaf = True; def render_POST(self, request): ... if __name__ == "__main__": factory = Site(HttpResource()) reactor.listenTCP(8000, factory) reactor.run()
class HttpResource(Resource):
isLeaf = True;
def render_POST(self, request):
...
if __name__ == "__main__":
factory = Site(HttpResource())
reactor.listenTCP(8000, factory)
reactor.run()
我创建了一个引发异常的简单test()函数:
def test():
print "test() called"
raise Exception("Exception raised!")
捕获程序输出中的异常消息(即“引发异常!”)
如果在render_POST()中调用test(),则会引发异常,并且输出会按预期显示消息:
Traceback (most recent call last):
raise Exception("Exception!")
exceptions.Exception: Exception!
但是,如果我在render_POST()中创建一个指向执行test()的回调的延迟,则可能仍会引发异常(客户端收到500个内部服务器错误),但不会显示异常错误消息(“引发异常!”短语)
问题
如何获取异常错误消息以显示它们何时由回调中的函数调用引起
更新1:提供演示代码(需要Twisted for server.py)**更新2:演示代码返回“尚未完成” client.py
import json, urllib2
if __name__ == "__main__":
while True:
cmd = raw_input("Enter cmd number (1, 2, or 0): ")
if cmd == str(1):
raw_data = {'cmd' : 'cmd1'}
elif cmd == str(2):
raw_data = {'cmd' : 'cmd2'}
elif cmd == str(0):
break;
req = urllib2.Request('http://localhost:8000')
req.add_header('Content-Type', 'application/json')
response = urllib2.urlopen(req, json.dumps(raw_data))
print response.read()
server.py
import json, time
from twisted.internet import reactor
from twisted.web.client import getPage
from twisted.web.resource import Resource
from twisted.web.server import Site, NOT_DONE_YET
def test():
print "test() called"
time.sleep(1)
raise Exception("Exception raised!")
def callback(result):
print "callback() called"
test()
class HttpResource(Resource):
isLeaf = True;
def render_POST(self, request):
msg = json.loads(request.content.getvalue())
if msg['cmd'] == 'cmd1': # call test() directly
test()
elif msg['cmd'] == 'cmd2': # call test() from callback
d = getPage('http://www.yahoo.com')
d.addCallbacks(callback, callback)
return NOT_DONE_YET
if __name__ == "__main__":
factory = Site(HttpResource())
reactor.listenTCP(8000, factory)
reactor.run()
这里有两个问题与您丢失的回溯有关 程序的第一个问题是,当您从
render\u POST
返回None
时,这会告诉twisted.web您已经完成了对请求的处理,应该立即关闭连接。当您的回调开始将一些数据推送到HTTP通道时,响应已经发送,数据被丢弃
第二个问题是,您根本没有将数据向外推送到连接。当render_POST本身引发异常时,调用它的代码可以捕获该异常。但是,调用render\u POST
的代码并不期望出现一个延迟的
,即使它发生了,您也不会在这里返回一个
还有第三个问题,那就是你使用的是time.sleep
,它冻结了你的整个程序,而不是deferLater
,它会返回一个Deferred
,它只会在以后触发,并允许并发任务继续进行。由于time.sleep
完全偏离了主题,无论是否包含它,行为都是相同的,我们可以忽略它:-)
有一种方法可以在Twisted本身中解决这个问题,但更简单的方法是使用它,它会自动为您处理延迟
使用Klein,您的示例如下:
import json
from klein import run, route
from twisted.web.client import getPage
def test():
print "test() called"
raise Exception("Exception raised!")
def callback(result):
print "callback() called"
test()
@route("/", methods=["POST"])
def example(request):
msg = json.loads(request.content.getvalue())
if msg['cmd'] == 'cmd1': # call test() directly
test()
elif msg['cmd'] == 'cmd2': # call test() from callback
d = getPage('http://www.yahoo.com')
return d.addCallbacks(callback, callback)
run("localhost", 8000)
注意
返回d.addCallbacks
;如果不返回
结果,它将继续以与现在大致相同的方式失败。请包括一个演示此问题的示例。我很感激您在描述中力求透彻,但由于我无法运行您的确切代码,我不知道您可能有什么问题。@Glyph谢谢您的建议。现在附加了工作代码。我已经尝试了您的示例,它确实为我打印了“callback()called”。此外,没有技术原因说明延迟调用与直接调用在打印方面的行为有所不同。也许值得在回调函数中添加一种不同类型的副作用,看看它是否被调用;您可能有一个更基本的问题。@RomanK应该显示“callback()called”——print语句是为了证明callback()确实被调用了。问题是接下来会发生什么。Callback()应该(并且确实,正如另一个print stmt所证明的)调用test()。Test()应在输出中显示异常消息,但不显示。这就是我遇到的问题。对不起,我应该提到test()也被调用并为我打印出来。我应该给出更好的演示代码。我的真实代码返回“尚未完成”且不使用时间。sleep:)如果我正确理解(并引用)您的话,“Twisted本身有一种解决此问题的方法”…您能告诉我如何操作吗?您已将其更正为使用尚未完成
,但它仍在调用时间。sleep:)。请张贴您的实际代码(可能在一个新问题中,以便我可以提供一个单独的答案)。