Python, Twisted, Django, reactor.run () problème à l'origine
-
13-10-2019 - |
Question
J'ai une application web Django. J'ai aussi un serveur sort écrit en utilisant la course tordue sur la même machine ayant django (en cours d'exécution sur localhost:8090
). L'idée étant lorsque l'utilisateur fait une action, la demande vient de Django qui se connecte à son tour à ce serveur et serveur torsadé envoie des données à Django. Enfin Django met ces données dans un certain modèle et sert html il à l'utilisateur.
Voici où j'ai un problème. Dans mon application Django, lorsque la demande vient créer un client simple tordu pour se connecter au serveur torsadé exécuter localement.
...
factory = Spell_Factory(query)
reactor.connectTCP(AS_SERVER_HOST, AS_SERVER_PORT, factory)
reactor.run(installSignalHandlers=0)
print factory.results
...
Le reactor.run()
est à l'origine d'un problème. Comme il est une boucle d'événements. La prochaine fois que ce même code est exécuté par Django, je suis incapable de se connecter au serveur. Comment peut-on gérer cela?
La solution
Les deux réponses ci-dessus sont corrects. Cependant, étant donné que vous avez déjà mis en place une orthographe serveur puis Exécuter comme un . Vous pouvez commencer par exécuter sur la même machine comme un processus séparé - à localhost:PORT
. À l'heure actuelle, il semble que vous avez une interface de protocole binaire très simple déjà -. Vous pouvez mettre en œuvre un client Python tout aussi simple en utilisant l'interface standard socket
de lib en mode bloquant
Cependant, je vous suggère de jouer avec twisted.web
et d'exposer une interface web simple. Vous pouvez utiliser JSON aux données de sérialisation et la désérialisation - qui est bien pris en charge par Django. Voici un exemple très rapide:
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())
Et pour l'exécuter, vous pouvez utiliser le fichier squelette .tac
suivant:
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)
L'exécution de votre service comme un autre service de première classe vous permet d'exécuter sur une autre machine si un jour vous trouvez la nécessité -. Exposer une interface web rend l'échelle facile à l'horizontale derrière un équilibreur de charge inverse de mandatement trop
Autres conseils
reactor.run()
devrait être appelé une seule fois dans votre programme. Ne pensez pas comme « commencer celui-ci demande que j'ai », pensez comme « commencer tous Twisted ».
Exécution du réacteur dans un thread d'arrière-plan est un moyen de contourner ce; alors votre application django peut utiliser blockingCallFromThread
dans votre application Django et utiliser une API Twisted comme vous API bloquer tout. Vous aurez besoin d'un peu de coopération de votre conteneur WSGI, cependant, parce que vous devez vous assurer que ce fond fil torsadé est démarré et arrêté à des moments appropriés (lorsque votre interprète est initialisé et démolie, respectivement).
Vous pouvez également utiliser Twisted comme contenant WSGI, et vous n'avez pas besoin pour démarrer ou arrêter quelque chose de spécial; blockingCallFromThread
va juste travailler immédiatement. Consultez l'aide en ligne de commande pour twistd web --wsgi
.
Vous devriez arrêter réacteur après avoir obtenu des résultats à partir du serveur Twisted ou un événement d'erreur / délai d'attente. Ainsi, sur chaque demande Django qui nécessite requête serveur Twisted vous devez exécuter réacteur, puis l'arrêter. Mais, ce n'est pas pris en charge par la bibliothèque Twisted - réacteur n'est pas redémarrant. Solutions possibles:
-
Utilisez du fil séparé pour le réacteur Twisted, mais vous devez déployer votre application django avec le serveur, qui supporte les longs fils en cours d'exécution (je ne maintenant toutes ces choses, mais vous pouvez écrire votre propre facilement: -.))
-
Ne pas utiliser Twisted pour mettre en œuvre le protocole client, il suffit d'utiliser le module de
socket
stdlib plaine.