Cómo configurar el lado del servidor Python con el lado del cliente javascript

Así que ya existe una configuración del progtwig Python que se ejecuta en la consola en la que debo desarrollar. Estaré construyendo una interfaz web GUI para la aplicación usando Javascript. Como yo

a. Ve a manejar la entrada / salida de este progtwig Python sin tocar el código original.

segundo. Vaya a enviar entradas de línea de consola al progtwig Python a través de llamadas de Javascript. He investigado solicitudes HTTP sin procesar / AJAX, pero no estoy seguro de cómo exactamente enviaría eso como entrada al progtwig Python.

a. Para manejar la entrada / salida del progtwig: Pexpect . Es bastante fácil de usar, y leer algunos de los ejemplos distribuidos con él debería enseñarle lo suficiente para comprender lo básico.

segundo. Interfaz de Javascript:

Bueno, yo uso gevent y es un servidor WSGI incorporado. (mira lo que es un servidor WSGI ( otro )). Debo tener en cuenta que este progtwig mantendrá un estado, por lo que puede administrar sus sesiones abiertas devolviendo un ID de sesión a su cliente javascript y almacenando su sesión pexpect en una variable global o en algún otro contenedor para que pueda completar la entrada y salida del progtwig a través de múltiples solicitudes AJAX independientes. Sin embargo, te lo dejo a ti, ya que no es tan simple.

Todo lo que haré con mi ejemplo es colocar la solicitud POST en algunos después de hacer clic en algo de su elección. (en realidad no funcionará porque algunas de las variables no están establecidas. Configúrelas).

Heres las partes relevantes:

   

Luego el servidor:

 # Python and Gevent from gevent.pywsgi import WSGIServer from gevent import monkey monkey.patch_all() # makes many blocking calls asynchronous def application(environ, start_response): if environ["REQUEST_METHOD"]!="POST": # your JS uses post, so if it isn't post, it isn't you start_response("403 Forbidden", [("Content-Type", "text/html; charset=utf-8")]) return "403 Forbidden" start_response("200 OK", [("Content-Type", "text/html; charset=utf-8")]) r = environ["wsgi.input"].read() # get the post data return r address = "youraddresshere", 8080 server = WSGIServer(address, application) server.backlog = 256 server.serve_forever() 

Si su progtwig está orientado a objetos, sería bastante fácil integrarlo. EDIT: No necesita ser orientado a objetos. y ahora he incluido algún código Pexpect

 global d d = someClass() def application(environ, start_response): # get the instruction password = somethingfromwsgi # read the tutorials on WSGI to get the post stuff # figure out WHAT to do global d success = d.doSomething() # or success = funccall() prog = pexpect.spawn('python someprogram.py') prog.expect("Password: ") prog.sendline(password) i = prog.expect(["OK","not OK", "error"]) if i==0: start_response("200 OK", [("Content-Type", "text/html; charset=utf-8")]) return "Success" elif i==1: start_response("500 Internal Server Error", [("Content-Type", "text/html; charset=utf-8")]) return "Failure" elif i==2: start_response("500 Internal Server Error", [("Content-Type", "text/html; charset=utf-8")]) return "Error" 

Otra opción que sugiero es Nginx + uWSGI. Si prefieres eso, también puedo darte algunos ejemplos de eso. Le brinda la ventaja de incorporar el servidor web en la configuración.

Para pasar sus datos de forma transparente desde javascript al progtwig Python externo, puede usar el protocolo WebSocket para conectar su servidor y javascript, y usar stdin / stdout para comunicarse con el progtwig externo desde el servidor.

Aquí hay un ejemplo del progtwig Python client.py :

 #!/usr/bin/env python """Convert stdin to upper case.""" for line in iter(raw_input, 'quit'): print line.upper() 

He creado un servidor utilizando el código del ejemplo de hello world websocket y la respuesta de SO sobre cómo crear un nuevo proceso en cada conexión entrante y redirigir todos los datos de entrada al estándar del proceso :

 #!/usr/bin/python """WebSocket CLI interface.""" import sys from twisted.application import strports # pip install twisted from twisted.application import service from twisted.internet import protocol from twisted.python import log from twisted.web.server import Site from twisted.web.static import File from txws import WebSocketFactory # pip install txws class Protocol(protocol.Protocol): def connectionMade(self): from twisted.internet import reactor log.msg("launch a new process on each new connection") self.pp = ProcessProtocol() self.pp.factory = self reactor.spawnProcess(self.pp, sys.executable, [sys.executable, '-u', 'client.py']) def dataReceived(self, data): log.msg("redirect received data to process' stdin: %r" % data) self.pp.transport.write(data) def connectionLost(self, reason): self.pp.transport.loseConnection() def _send(self, data): self.transport.write(data) # send back class ProcessProtocol(protocol.ProcessProtocol): def connectionMade(self): log.msg("connectionMade") def outReceived(self, data): log.msg("send stdout back %r" % data) self._sendback(data) def errReceived(self, data): log.msg("send stderr back %r" % data) self._sendback(data) def processExited(self, reason): log.msg("processExited") def processEnded(self, reason): log.msg("processEnded") def _sendback(self, data): self.factory._send(data) application = service.Application("ws-cli") _echofactory = protocol.Factory() _echofactory.protocol = Protocol strports.service("tcp:8076:interface=127.0.0.1", WebSocketFactory(_echofactory)).setServiceParent(application) resource = File('.') # serve current directory INCLUDING *.py files strports.service("tcp:8080:interface=127.0.0.1", Site(resource)).setServiceParent(application) 

La parte del cliente web, sendkeys.html :

  Send keys using websocket and echo the response    
Here you should see the typed text in UPPER case

y sendkeys.js :

 // send keys to websocket and echo the response $(document).ready(function() { // create websocket if (! ("WebSocket" in window)) WebSocket = MozWebSocket; // firefox var socket = new WebSocket("ws://localhost:8076"); // open the socket socket.onopen = function(event) { socket.send('connected\n'); // show server response socket.onmessage = function(e) { $("#output").text(e.data); } // for each typed key send #entry's text to server $("#entry").keyup(function (e) { socket.send($("#entry").attr("value")+"\n"); }); } }); 

Intentarlo:

  • descarga esta esencia
  • instale twisted , txws :

     $ pip install twisted txws 
  • correr:

     $ twistd -ny wscli.py 
  • Visite http://localhost:8080/

  • haga clic en sendkeys.html y escriba algo

Probablemente quieras Flask , junto con el módulo json .

Django es otra opción, pero probablemente sea un nivel demasiado alto para sus necesidades.

Esto depende de qué tipo de aplicación está ajustando y de cómo sus opciones de GUI se traducen en comandos de aplicación. Pero tienes dos objectives aquí:

  1. Escribir un contenedor para permitirle leer la salida de su progtwig y proporcionarle información.

  2. Hacer un servidor web para recibir eventos GUI y convertirlos en comandos para pasar a su “contenedor”

He hecho algo como lo que necesitas hacer.

  1. Esencialmente necesitas convertir los flujos de socket en comandos discretos. La herramienta de facto para esto es esperar , y cualquiera de sus envoltorios (he usado pexpect , el envoltorio Python, y tuve una buena experiencia con él).

  2. Esta parte podría no ser simple. El problema es que su progtwig subyacente se está ejecutando de manera persistente, por lo que su servidor web debe estar bien informado sobre el progtwig en todas las solicitudes. La otra opción es que su servidor web simplemente se vuelva a adjuntar al proceso y emita los comandos, y envíe una respuesta cuando se encuentre en la secuencia de la salida estándar, pero puede terminar con tiempos de respuesta prolongados dependiendo de la velocidad progtwig es. También existe la discrepancia de que las solicitudes de AJAX son asíncronas, mientras que su progtwig subyacente es síncrono. Así que sí, esto puede ser bastante complejo. Realmente depende de su progtwig. Si pudiera agregar algunos detalles sobre cómo son el progtwig y la GUI, sería de ayuda.