3

I have a web project using php and a python script which modifies folders. I want to execute some javascript on the website based on eg. a folder creation done in the python script.

My idea was to work with python socketio. I have the basic connection notification working and emits from the js on a website are being handle by the js as well.

The problem is that I cannot emit any events after starting the eventlet server. I tried setting up the async mode but it does not have the desired result.

Here is my code so far:

import socketio
from flask import Flask, render_template
import eventlet

import sys

sio = socketio.Server(async_mode='eventlet')
app = Flask(__name__)

@sio.on('connect')
def connect(sid, environ):
    print('connect ', sid)
    sio.emit('channel', 'new connection')
    sys.stdout.flush()

@sio.on('mes')
def message(sid, data):
    print('message ', data)
    sys.stdout.flush()

app = socketio.Middleware(sio)

eventlet.wsgi.server(eventlet.listen(('', 8000)), app)

# create folder HERE and emit event which will be sent to browser

UPDATE:

I started using threads like in the following code: (Is there a problem with using threads like that? Or another better approach?)

import socketio
from flask import Flask, render_template
import eventlet

import sys
import thread
import time

sio = socketio.Server(async_mode='gevent')

@sio.on('connect')
def connect(sid, environ):
    print('connect ', sid)
    sio.emit('channel', 'new connection')
    sys.stdout.flush()

@sio.on('mes')
def message(sid, data):
   print('message ', data)
   sio.emit('channel', 'yeah')
   sys.stdout.flush()

from gevent import pywsgi
from geventwebsocket.handler import WebSocketHandler
app = socketio.Middleware(sio)

def worker( threadName ):
   count = 1
   while count > 0:
      time.sleep(1)
      # trying to emit message HERE
      sio.emit('mes', 'foo ' + str(count))
      print "working " + str(count)
      sys.stdout.flush()
      count += 1

def server( threadName ):
   print "server starting"
   sys.stdout.flush()
   pywsgi.WSGIServer(('', 8000), app, handler_class=WebSocketHandler).serve_forever()

try:
   thread.start_new_thread( worker, ("Thread-1", ) )
   thread.start_new_thread( server, ("Thread-2", ) )
except:
   print "Error: unable to start thread"

while 1:
   pass

The problem now is that the sio.emit('mes', 'foo ' + str(count)) emits the message - but the browser only catches it every 20~30s and then all missing events are handled. See the picture with the frames from the dev console.

network frames

rambii
  • 451
  • 4
  • 11
  • Not sure I understand. Are you trying to run code at the bottom, right after the server is started? That's now how things work, the server creation call does not return. – Miguel Grinberg May 13 '16 at 16:42
  • @Miguel Yes that is what I was trying to do. I updated my question with my new code using threads - is it right to use threads like that? And do you know why the new events are not being picked up immediately? – rambii May 13 '16 at 17:38
  • You don't really need to put the server in a background thread. Just start the worker thread before you start the server on the main thread. Besides that, all I can think of is that you should use `gevent.sleep()` instead of `time.sleep()`. – Miguel Grinberg May 13 '16 at 20:19
  • Strip question to one code and one problem to get a definite answer. Otherwise, for current approach: delete either eventlet or gevent. Both in same process is asking for trouble. Also add `eventlet/gevent.monkey_patch()` at the very beginning, before executing any other import. – temoto May 14 '16 at 06:36
  • @Miguel not putting the server in a separate thread seemed to solve my issue. Thanks for your comments and help. However `gevent.sleept()`didn't seem to have the same effect as the `time.sleep()` - the worker didn't output anything anymore. – rambii May 15 '16 at 09:44
  • @temoto thanks for your advice. I cleaned the code and removed the eventlet. Monkeypatching was causing an exception when I was working on that. Fortunately I was able to solve the issue differently. – rambii May 15 '16 at 09:46
  • @rambii I said `gevent.sleep()`, but should have said `eventlet.sleep()`. I confused the two frameworks. – Miguel Grinberg May 15 '16 at 17:51

1 Answers1

2

With the comments by @Miguel I accomplished to reach to goal I was aiming for.

I removed the thread for the server which seemed to have the desired effect. Now the developer console shows a emitted event every time the worker fires an event.

import socketio
import sys
import thread
import time

sio = socketio.Server(async_mode='gevent')

@sio.on('connect')
def connect(sid, environ):
    print('connect ', sid)
    sio.emit('channel', 'new connection')
    sys.stdout.flush()

@sio.on('mes')
def message(sid, data):
   print('message ', data)
   sio.emit('channel', 'yeah')
   sys.stdout.flush()

from gevent import pywsgi
from geventwebsocket.handler import WebSocketHandler
app = socketio.Middleware(sio)

def worker( threadName ):
   count = 1
   while count > 0:
      time.sleep(5)
      sio.emit('mes', 'foo ' + str(count))
      print "working " + str(count)
      sys.stdout.flush()
      count += 1

try:
   thread.start_new_thread( worker, ("Thread-1", ) )
except:
   print "Error: unable to start thread"

print "server starting"
sys.stdout.flush()
pywsgi.WSGIServer(('', 8000), app, handler_class=WebSocketHandler).serve_forever()
rambii
  • 451
  • 4
  • 11