Python,Twisted,Django,reactor.run()导致问题

时间:2010-12-26 17:26:44

标签: python django twisted twisted.client twisted.internet

我有一个Django Web应用程序。我也有一个拼写服务器使用django(在localhost:8090上运行)在同一台机器上使用扭曲运行编写。这个想法是当用户做一些动作时,请求来到Django,然后Django连接到这个扭曲的服务器&服务器将数据发送回Django。最后,Django将这些数据放在一些html模板中。将它交还给用户。

这是我遇到问题的地方。在我的Django应用程序中,当请求进入时,我创建一个简单的扭曲客户端连接到本地运行的扭曲服务器。

...
        factory = Spell_Factory(query) 
        reactor.connectTCP(AS_SERVER_HOST, AS_SERVER_PORT, factory)
        reactor.run(installSignalHandlers=0)
        print factory.results
...

reactor.run()导致问题。因为它是一个事件循环。下次Django执行相同的代码时,我无法连接到服务器。如何处理这个?

3 个答案:

答案 0 :(得分:4)

以上两个答案都是正确的。但是,考虑到您已经实现了拼写服务器,那么将其作为一个运行。您可以首先在同一台计算机上运行它作为单独的进程 - localhost:PORT。现在看来你已经有了一个非常简单的二进制协议接口 - 你可以在阻塞模式下使用标准的lib socket接口实现一个同样简单的Python客户端。

但是,我建议使用twisted.web并展示一个简单的Web界面。您可以使用JSON来序列化和反序列化数据 - 这是Django的良好支持。这是一个非常简单的例子:

import json
from twisted.web import server, resource
from twisted.python import log

class Root(resource.Resource):
    def getChild(self, path, request):
        # represents / on your web interface
        return self

class WebInterface(resource.Resource):
    isLeaf = True
    def render_GET(self, request):
        log.msg('GOT a GET request.')
        # read request.args if you need to process query args
        # ... call some internal service and get output ...
        return json.dumps(output)

class SpellingSite(server.Site):
    def __init__(self, *args, **kwargs):
        self.root = Root()
        server.Site.__init__(self, self.root, **kwargs)
        self.root.putChild('spell', WebInterface())

要运行它,您可以使用以下框架.tac文件:

from twisted.application import service, internet

site = SpellingSite()
application = service.Application('WebSpell')
# attach the service to its parent application
service_collection = service.IServiceCollection(application)
internet.TCPServer(PORT, site).setServiceParent(service_collection)

如果您发现需要,将服务作为另一个第一类服务运行,您可以在另一台计算机上运行它 - 公开Web界面可以轻松地在反向代理负载平衡器后面水平扩展它。

答案 1 :(得分:3)

reactor.run()只能在整个程序中调用一次。不要把它想象成“从我开始这一个请求”,把它想象成“开始全部扭曲”。

在后台线程中运行reactor是解决这个问题的一种方法;然后你的django应用程序可以在你的Django应用程序中使用blockingCallFromThread并像使用任何阻塞API一样使用Twisted API。但是,您需要从WSGI容器中进行一些合作,因为您需要确保在适当的时间启动和停止此背景Twisted线程(分别初始化和拆除解释器时)。

您也可以使用Twisted作为WSGI容器,然后您不需要启动或停止任何特殊的操作; blockingCallFromThread将立即发挥作用。请参阅twistd web --wsgi的命令行帮助。

答案 2 :(得分:1)

在从Twisted服务器获得结果或发生某些错误/超时后,您应该停止reactor。因此,在需要查询Twisted服务器的每个Django请求中,您应该运行reactor然后停止它。但是,Twisted库不支持它 - reactor不能重启。可能的解决方案:

  • 为Twisted reactor使用单独的线程,但是您需要使用服务器部署django应用程序,该服务器支持长时间运行的线程(我现在不用任何这些,但您可以轻松编写自己的: - 。))

  • 不要使用Twisted来实现客户端协议,只需使用plain stdlib的socket模块即可。