Send keys using websocket and echo the response

How to set up Python server side with javascript client side

So there is already a Python program set up that runs on the console that I must build upon. I will be building a web GUI interface for the application using Javascript. How would I: a. Go about handling the input/output of this Python program without touching the original code. b. Go about sending console-line inputs to the Python program via Javascript calls. I’ve looked into raw HTTP requests/AJAX, but I’m not sure how exactly I would go about sending that as input to the Python program.

I assume your Python program communicates with the world via stdin/stdout? And what you need to do is «wrap» the program into something else that would allow communication with a browser? Is that a correct description of what you want to do?

4 Answers 4

a. To handle input/output of the program: Pexpect. It’s fairly easy to use, and reading some of the examples distributed with it should teach you enough to get the basics down.

Well, I use gevent and it’s built-in WSGI server. (look up what a WSGI server (another) is). I should note that this program will keep a state, so you can manage your open sessions by returning a session ID to your javascript client and storing your pexpect session in a global variable or some other container so that you can complete the program’s input and output across multiple independent AJAX requests. I leave that up to you, however, as that is not as simple.

Читайте также:  Css get x heights

All my example will do is put the POST request in some after clicking something of your choice. (it won’t actually work because some of the variables are not set. Set them.)

   
# 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() 

If your program is Object Oriented, it’d be fairly easy to integrate this. EDIT: Doesn’t need to be object oriented. and I have now included some Pexpect code

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" 

Another option I suggest is Nginx + uWSGI. If you would prefer that, I can give you some examples of that as well. It gives you the benefit of incorporating the webserver into the setup.

The part «Go about handling the input/output of this Python program without touching the original code.» is missing.

You launch a new subprocess on each request. There is no back and forth between javascript and the subprocess, just a single request/reply. Though it seems what the OP wanted.

It would require multiple javascript calls with a saved state in the program to achieve what you describe, yes. If he finds that unsuitable, he can look into uWSGI which I believe supports long-polling such that he could have the back and forth you are talking about. I’m not familiar enough with it to provide the examples, however.

Looking at your example, it is very well done. It’s more of a matter of coding style and preference as I find my solution a bit more verbose but simpler to program than using Twisted and websockets. Both should work.

To pass transparently your data from javascript to external Python program you could use WebSocket protocol to connect your server and javascript, and use stdin/stdout to communicate with the external program from the server.

Here’s an example Python program client.py :

#!/usr/bin/env python """Convert stdin to upper case.""" for line in iter(raw_input, 'quit'): print line.upper() 
#!/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) 

The web-client part, sendkeys.html :

    
// 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"); >); > >); 
  • download this gist
  • install twisted , txws :

Источник

JS клиент и Python сервер, как передавать данные через socket?

Вопрос, как заставить принимать данные с сервера клиенту JS? +Python должен постоянно отправлять данные в клиент Js, пока запущен сервер.
(В представленном коде сервер выдает ошибку:Traceback (most recent call last):
А клиент выдает Запрос из постороннего источника заблокирован: Политика одного источника запрещает чтение удаленного ресурса на localhost:9090/socket.io/?EIO=3&transport=polling&. (Причина: отсутствует заголовок CORS «Access-Control-Allow-Origin»).(неизвестен)
)
Камнями сильно не кидайтесь, если ответ очевиден.

Дело в том что на клиенте вы используете протокол websocket, а на сервере чистые tcp сокеты. Если вам нужен websocket на python, то посмотрите https://flask-socketio.readthedocs.io/en/latest/ он самый простой на мой взгляд.
Если хотите делать протокол самостоятельно то вот спецификация https://tools.ietf.org/html/rfc6455

Протокол Socket.IO имеет мало отношения к голым WebSocket, несмотря на то, что построен поверх них. На клиент, кстати, тоже придется тащить специальный Socket.IO-клиент (и изучать тоны документации специально по нему).
ИМХО: Socket.IO — лишний уровень абстракции, не дающий принципиально ничего такого, чего не дает голый WebSocket (кроме совместимости со старыми браузерами, вышедшими из употребления).

Pickto

Pickto

nirvimel: А нет пути проще, так как все будет происходить в локальной системе и мне нужно что бы python отправлял в js значения переменных?

Pickto

nirvimel: Когда я начинал я думал это не займет много времени у меня, так как это всего лишь часть моего проекта

Источник

Оцените статью