Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jquery/85.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
TwistedPython-延迟';s回调&x27;s函数调用,引发的异常未显示在标准输出中_Python_Exception_Twisted - Fatal编程技术网

TwistedPython-延迟';s回调&x27;s函数调用,引发的异常未显示在标准输出中

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()

测试设置

我有一个异步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()
我创建了一个引发异常的简单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:)。请张贴您的实际代码(可能在一个新问题中,以便我可以提供一个单独的答案)。