连接两次扭曲 - 如何正确地做到这一点?

时间:2009-12-30 08:44:45

标签: twisted

我想使用twisted(和StarPy这是asterisk ami的协议实现)连接到星号服务器。应用程序在那里启动传出传真。我发现了一些关于我的问题的提示,但我无法找到如何正确处理这个问题。

第一份传真正确发送。

  

问题是,如果我打电话给   第二次,应用程序保持   挂在主循环中。

我知道我可能不会这样做:

from starpy import manager
from twisted.internet import reactor

def main():
    f = manager.AMIFactory(cUser, cPass)
    print "Login"
    df = f.login(cServer, cPort)

    def onLogin(protocol):
        print "Logoff again"
        df = protocol.logoff()

        def onLogoff( result ):
            print "Logoff erfolgt"
            reactor.stop()

        return df.addCallbacks( onLogoff, onLogoff )

    def onFailure( reason ):
        print "Login failed"
        print reason.getTraceback()

    df.addCallbacks( onLogin, onFailure )
    return df

if __name__ == "__main__":
    reactor.callWhenRunning( main )
    reactor.run(installSignalHandlers=0)
    print "runned the first time"

    reactor.callWhenRunning( main )
    reactor.run(installSignalHandlers=0)
    print "will never reach this point"

我简化了代码 - 它再次没有登录+注销。它永远不会从第二个reactor.run()调用返回。

这是如何正确完成的?我被困在这里 - 提前谢谢。

最诚挚的问候, 弗洛里安。

4 个答案:

答案 0 :(得分:9)

正如iny所说,只需拨打一次reactor.runreactor.stop即可完成所有操作。

如果我们考虑您发布的示例代码,我们会看到它采取以下步骤:

  1. 启动反应堆
    • 连接,发送传真,断开连接
    • 停止反应堆
    • 启动反应堆
    • 连接,发送传真,断开连接
    • 停止反应堆
  2. 如果我们只删除第3步和第4步,那么程序实际上会做一个非常合理的事情。

    以下是您实施第3步的方法:

    def onLogoff( result ):
        print "Logoff erfolgt"
        reactor.stop()
    

    这导致第一次调用reactor.run返回,为您执行第4步扫清了道路:

    reactor.callWhenRunning( main )
    reactor.run(installSignalHandlers=0)
    

    所以,这里的一般想法是跳到第5步,而不是执行第3步和第4步。考虑如果你重新定义onLogoff这样会发生什么:

    def onLogoff( result ):
        print "Logoff erfolgt"
        main()
    

    并删除示例的最后三行。这实际上会给你一个无限循环,因为在第二次断开连接后运行相同的onLogoff并开始第三次连接。但是,您可以使用main函数的参数来控制重启行为。

    一旦这有意义,您可能需要考虑将重试注销从main函数移出到__main__块中定义的回调。这是Deferreds功能的重要组成部分:它可以让您在事件源(在本例中为传真发送功能)的实现与处理结果事件的代码(发送第二个传真,或者退出,在这种情况下)。

答案 1 :(得分:3)

您无法重启反应堆。换句话说,您只能调用一次reactor.run()。

相反,它可以在一个反应​​堆运行中完成所需的一切。

答案 2 :(得分:3)

感谢您的回答,我现在还没有实施解决方案,但我现在知道如何做到这一点......

这是我学到的东西的简短摘要。

首先,简而言之 - 我遇到的扭曲问题:

  1. 我不明白扭曲的异步基础知识。我在gui-frameworks中使用了类似的东西,但很长一段时间都没有看到它的好处。
  2. 其次,我试图多次考虑事件循环的同步调用。这在我看来是必要的,因为我一次不能使用多个传出传真线。因为twisted的事件循环不可重启,所以这是不可取的。正如我在文档中看到的那样,“deferToThread”可以帮助我,但我认为这不是最好的解决方案。
  3. 在我的概念中,我解决了这些问题:

    我需要进行大量的重新思考,但只要你明白它就会很容易。

    感谢iny和Jean-Paul Calderone的帮助。

答案 3 :(得分:0)

如果您仍在寻找解决方案......我遇到了同样的问题。我有一个脚本使用Twisted来执行远程服务器上的程序。我需要一种从django应用程序中同步运行该脚本的方法。我最终做的是让我的Twisted脚本调用远程服务器,然后打印到stdout。然后从我的Django应用程序中,我通过subprocess.Popen执行该脚本并设置stdout = PIPE,这样我就可以从我的Twisted脚本中捕获输出并在我的Django应用程序中使用它。

这不是很理想,并且几乎违背了Twisted的目的,但这已经超过了“无法再次调用reactor.run(),因为Twisted脚本每次都在它自己的进程中运行

这最终对我很有用,听起来和你所处的情况非常相似。我希望这会有所帮助。祝好运。 (如果您认为它会有所帮助,我可以发布一些代码示例,请告诉我。)