使用twisted连接两次-如何正确连接?
我想使用twisted(和StarPy,它是asterisk ami的协议实现)连接到asterisk服务器。应用程序在那里启动传出传真。我发现了一些关于我的问题的提示,但我不知道如何正确处理这个问题 第一份传真发送正确 问题是,如果我打电话给twisted 第二次,应用程序保持 挂在主回路中 我知道我可能不会在这里这样做:使用twisted连接两次-如何正确连接?,twisted,Twisted,我想使用twisted(和StarPy,它是asterisk ami的协议实现)连接到asterisk服务器。应用程序在那里启动传出传真。我发现了一些关于我的问题的提示,但我不知道如何正确处理这个问题 第一份传真发送正确 问题是,如果我打电话给twisted 第二次,应用程序保持 挂在主回路中 我知道我可能不会在这里这样做: from starpy import manager from twisted.internet import reactor def main(): f = m
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()调用返回
如何正确地做到这一点?我被困在这里了-提前谢谢
致以最良好的祝愿,
Florian.你不能重启反应堆。换句话说,您只能调用reactor.run()一次
相反,您可以在一次反应堆运行中完成所有需要的操作。正如iny所说,您只需一次调用
反应堆。运行和反应堆。停止
如果我们考虑您发布的示例代码,我们会看到它采取以下步骤:
启动反应堆
- 连接、发送传真、断开连接
- 停止反应堆
- 启动反应堆
- 连接、发送传真、断开连接
- 停止反应堆
如果我们只删除第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
函数,并移到\uuuu main\uuu
块中定义的回调中。这是延迟功能的很大一部分:它使您能够在事件源的实现(在本例中是传真发送功能)和处理结果事件的代码(在本例中是发送第二份传真或退出)之间保持适当的分离。谢谢您的回答,我现在还没有实现一个解决方案,但我知道我现在该怎么做
这里是我学到的东西的简短总结
首先,简而言之——我在twisted上遇到的问题:
我不理解twisted的异步基础知识。我在gui框架中使用了类似的东西,但很长一段时间没有看到它的好处
其次,我多次尝试考虑事件循环的同步调用。在我看来,这是必要的,因为我一次只能使用一条外发传真线。由于twisted的事件循环不可重新启动,因此没有选项。正如我在文档中所读到的,“deferToThread”可以在这里帮助我,但我认为这不是最好的解决方案
在我的观念中,我解决了这些问题:
- 使用defer.DeferredSemaphore(),允许我将并发限制为1。
我在这里找到了一个例子:
- 随时给twisted打电话,让延期者做工作(发送传真)
- 将传真状态写入数据库并发送回执邮件将从延迟者调用
我需要很多的重新思考,但一旦你得到它,它看起来真的很容易
感谢iny和Jean-Paul Calderone的帮助。如果您仍在寻找解决方案。。。我也有同样的问题。我有一个脚本,它使用Twisted在远程服务器上执行程序。我需要一种在django应用程序中同步运行该脚本的方法。我最后做的是让我的Twisted脚本调用远程服务器并打印到stdout。然后,在Django应用程序中,我通过subprocess.Popen执行该脚本,并设置stdout=PIPE,这样我就可以从Twisted脚本中捕获输出,并在Django应用程序中使用它
这并不是很理想,而且几乎违背了Twisted的目的,但这已经克服了“无法再次调用reactor.run(),因为Twisted脚本每次都在它自己的进程中运行”
这对我来说确实非常有效,而且听起来与您所处的情况非常相似。我希望这会有所帮助。祝您好运。(如果您认为这会有所帮助,我可以发布一些代码示例,请告诉我).是的,这也是我在网上发现的。但我无法弄清楚我需要如何处理这个问题。也许你可以给我指出正确的方向:*我什么时候启动反应器?应用程序启动时还是第一次使用时?*我如何让一个反应器1.连接/2.发送传真/3.多次断开连接?我卡住了。我投资了ed hours开发和阅读手册-我只是找不到答案…提前谢谢。好吧,你给我一个想法。我必须再次阅读延迟的文档。也许这会阻止我撞墙。有没有办法在不停止反应堆的情况下关闭传出TCP连接?我不喜欢这个想法TCP会话一直处于打开状态…谢谢。谢谢,我不喜欢这个。twisted中我唯一不喜欢的是,它(在我的配置中)保持连接打开,而不是关闭它并等待再次需要它。我不明白为什么这种设计有意义。异步是有意义的-即使我需要一些时间来理解。无论如何,谢谢。这就是为什么我使用子进程,当子进程存在时,连接关闭。当我再次调用我的子进程时,它会打开并关闭它完成后关闭。您始终可以调用transport.loseConnection()