Giter VIP home page Giter VIP logo

Comments (57)

gordol avatar gordol commented on May 18, 2024 45

@djpimp2010 here is an example that works, using a "green thread", or greenlet, with eventlet as @miguelgrinberg suggested. This would work much the same with gevent too... It's very similar to your code, except we're not using the stdlib Thread module.

#!/usr/bin/env python

import eventlet
eventlet.monkey_patch()

from flask import Flask
from flask_socketio import SocketIO

app = Flask(__name__)
socket = SocketIO(app, logger=True, engineio_logger=True)

def bg_emit():
    socket.emit('bg_emit', dict(foo='bar'))

def listen():
    while True:
        bg_emit()
        eventlet.sleep(5)

eventlet.spawn(listen)

if __name__ == '__main__':
    socket.run(app, host='127.0.0.1')

You should then see something like the following:

Server initialized for eventlet.
(18852) wsgi starting up on http://127.0.0.1:5000/
emitting event "bg_emit" to all [/]
emitting event "bg_emit" to all [/]
emitting event "bg_emit" to all [/]

from python-socketio.

samwwwblack avatar samwwwblack commented on May 18, 2024 10

Have a read of this as it explains what's needed to do cross process/thread messaging.

from python-socketio.

gordol avatar gordol commented on May 18, 2024 8

Actually, the server supports threads now too, I believe!

See the documentation that was already linked above:
https://python-socketio.readthedocs.io/en/latest/#using-a-message-queue

Standard Threading Library
While not comparable to eventlet and gevent in terms of performance, the Socket.IO server can also be configured to work with multi-threaded web servers that use standard Python threads. This is an ideal setup to use with development servers such as Werkzeug. Only the long-polling transport is currently available when using standard threads.

Instances of class socketio.Server will automatically use the threading mode if neither eventlet nor gevent are not installed. To request the threading mode explicitly, the async_mode option can be given in the constructor:

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

A server configured for threading is deployed as a regular web application, using any WSGI complaint multi-threaded server. The example below deploys an Socket.IO application combined with a Flask web application, using Flask’s development web server based on Werkzeug:

sio = socketio.Server(async_mode='threading')
app = Flask(__name__)
app.wsgi_app = socketio.Middleware(sio, app.wsgi_app)

# ... Socket.IO and Flask handler functions ...

if __name__ == '__main__':
    app.run(threaded=True)

When using the threading mode, it is important to ensure that the WSGI server can handle multiple concurrent requests using threads, since a client can have up to two outstanding requests at any given time. The Werkzeug server is single-threaded by default, so the threaded=True option is required.

Note that servers that use worker processes instead of threads, such as gunicorn, do not support a Socket.IO server configured in threading mode.

from python-socketio.

miguelgrinberg avatar miguelgrinberg commented on May 18, 2024 6

@goranlundberg first of all, let's clarify that your question applies to Flask-SocketIO. This package is python-socketio, and it is a dependency of the Flask specific one.

Why is emit behaving in two ways? Shouldn't it be socketio.emit(...) everywhere? Why is emit(...) without socketio working sometimes? I'm really confused.

The emit() function takes information from the request context by default, with available overrides given in arguments you provide. The socketio.emit() takes information only from arguments, and as such, does not require a request context to be active. The most significant difference between these two, is that emit() will, by default, only emit to the client in the request context, so it is a very convenient function to use to send a private response to the client inside an event handler function for that client. The socketio.emit(), on the other side, defaults to broadcast to all clients, since it does not have the context to know who to send the event.

from python-socketio.

ageir avatar ageir commented on May 18, 2024 4

EDIT:

Solved it! Stupid mistake! Forgot to add namespace to the emit.
add_log() should look like this:

def add_log(msg):
    socketio.emit('log', {'time': time.ctime(), 'data': msg}, namespace='/test')

Hope it helps someone else.

-----------------------------------------------------------------------------------------------------------------

I basically have the same problem and using start_background_task as @xtreeio mentions.
Please read my inline comments in the code below.

Two questions:

  1. Why is emit behaving in two ways? Shouldn't it be socketio.emit(...) everywhere? Why is emit(...) without socketio working sometimes? I'm really confused.

  2. Why is the emit in add_log not working from the background tasks? My guess is that it needs socketio.emit(...) and calling it from test_connect() does not. Do I have to write separate functions to use with the background tasks? Seems really stupid to have to do that for the same function.

Hope someone can shed some light over this behaviour. Thanks!

#imports here
app = Flask(__name__)

async_mode = None
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app, async_mode=async_mode)

main_thread = None

def main_thread_worker():
    while True:
        socketio.sleep(1)
        #the following emit works fine
        socketio.emit('main',
                      {'data': 'main_thread_data'},
                      namespace='/test')
        #this does not work, out of context error.
        add_log("add this to log")

def add_log(msg):
    #this works when called from test_connect(), seems strange. Shouldn't it be socketio.emit(..) like below ????
    emit('log', {'time': time.ctime(), 'data': msg})
    #this does not work when called from test_connect(), why? confused?
    socketio.emit('log', {'time': time.ctime(), 'data': msg})

@app.route('/')
def index():
    return render_template('index.html')


@socketio.on('connect', namespace='/test')
def test_connect():
    global main_thread
    #here add_log works fine...
    add_log("Connected")
    if(main_thread is None):
        main_thread = socketio.start_background_task(target=main_thread_worker)
        #here also.
        add_log("Started main thread.")


if __name__ == '__main__':
    socketio.run(app, "192.168.1.10", 5000, debug=True)

from python-socketio.

miguelgrinberg avatar miguelgrinberg commented on May 18, 2024 3

The OP is not doing multi-process, so all the advice above regarding redis/rabbitmq does not apply.

from python-socketio.

gordol avatar gordol commented on May 18, 2024 2

@djpimp2010

Re: RuntimeError('working outside of request context')

http://flask.pocoo.org/docs/0.10/api/#flask.copy_current_request_context

flask.copy_current_request_context(f)
A helper function that decorates a function to retain the current request context. This is useful when working with greenlets. The moment the function is decorated a copy of the request context is created and then pushed when the function is called.

Example:

import gevent
from flask import copy_current_request_context

@app.route('/')
def index():
    @copy_current_request_context
    def do_some_work():
        # do some work here, it can access flask.request like you
        # would otherwise in the view function.
        ...
    gevent.spawn(do_some_work)
    return 'Regular response'

from python-socketio.

prokher avatar prokher commented on May 18, 2024 2

Dear colleagues,

I think that the restriction that all threads must be greenthreads is too restrictive. Consider you have a working thread which performs mathematical operation using numpy. This operation may take a while and there is no possibility to call sleep function from there, but since numpy is implemented in C it releases GIL during calculations, so Python interpreter performs quite well in parallel with such calculations. So the nice way to do such calculations is to fork a thread with numpy code.

When math calculations finish I need to somehow notify the eventloop where socket io server lives in, so it can notify the user by sending a message. The problem is that I cannot find the proper way to invoke the code in the event loop from my working thread. I do realize that there is a workaround with listener based on using sleep function. I think it is not the solution of the problem. It is polling which obviously contradicts to the whole idea of asynchronous approach.

The proper solution would be to provide the thread-safe method which accepts function to call from the event loop next time it is possible. Please, take a look how it is implemented in the Tornado server: http://www.tornadoweb.org/en/stable/ioloop.html#tornado.ioloop.IOLoop.add_callback . I think it is the solution of the problem discussed in this post.

Best regards,
Alexander.

from python-socketio.

prokher avatar prokher commented on May 18, 2024 1

Dear @gordol and @miguelgrinberg, thank you for your comments!

I think I understand the difference between native threads and green ones quite well, and realize how they can be used together. You are right, using highly computational intensive thread in the process of IO server is not a good idea, but that was not the point, just an example of using native working thread together with the event loop.

My point is there could be quite normal use-cases when developer desires to send a message to socket.io client from a separate (not eventloop) thread. More strictly speaking, submit the function to be invoked from socket.io event loop next time it spins (or, I suspect, when it is going to invoke 'select' function).

Just to make my point clear I mentioned Tornado server implementation. I suppose the implementation of method like Tornado's "IOLoop.add_callback" does not contradict to any of fundamental principles behind socket.io server.

I do realize, that typically we could use message broker like Redis or RabbitMQ, and use task managing system like Celery, which I do really like, btw. But there are cases when you are restricted to a single process. And I am dealing with such requirement at the moment. The idea is quite simple, I am writing a desktop application which has socket.io interface (server) and may perform a 1 or 2 long-running jobs in a worker threads. Once job finishes I need to notify socket.io client. That is it. Current implementation contains while True: eventlet.sleep(...) kludge, but it a polling and just weird. Tornado's "IOLoop.add_callback" is much elegant solution to allow separate threads to submit arbitrary function (e.g. sending message to client) to the main event loop.

Best regards,
Alexander.

from python-socketio.

gordol avatar gordol commented on May 18, 2024 1

If you're using Socket.IO, then use Socket.IO to send the message, have both threads communicating via a common channel. Otherwise, communication between threads, I agree, has nothing to do with this library, other than in-so-much as this library can allow one to use Socket.IO as a bus for communication between protothreads, threads, processes, or even other servers.

Are you simply not instantiating a second instance of a socket.io client in your other thread, and are trying to use the resource from the origin thread? Why fight the tooling like that?

from python-socketio.

NotSureAbout avatar NotSureAbout commented on May 18, 2024

Are you using Redis or RabbitMQ?

from python-socketio.

djpimp2010 avatar djpimp2010 commented on May 18, 2024

Just reviewed my previous code (with Flask-SocketIO) and I remembered wrong. I could emit from within a HTTP route, but didn't have the background thread in the program at that time. Just tried using Flask-SocketIO and I get the same problem.

RuntimeError('working outside of request context')

from python-socketio.

djpimp2010 avatar djpimp2010 commented on May 18, 2024

I am not using either of those, just flask and socketio.

from python-socketio.

djpimp2010 avatar djpimp2010 commented on May 18, 2024

An example of my code is:

application = Flask(__name__)
socket = SocketIO(application)

class foo:
    def bar():
        # do stuff
        socket.emit('custom','test-data')

def listen():
    foo = foo()
        while True:
            foo.bar()
            time.sleep(60)

@application.route('/')
def home:
    socket.emit('custom','test-data2')
    return 'HELLO WORLD'

@socket.on('custom1')
def a(data):
    pass

t = Thread(target=listen)
t.start()

if __name__ == '__main__':
    socket.run(application, host='0.0.0.0')

from python-socketio.

djpimp2010 avatar djpimp2010 commented on May 18, 2024

within the thread, bar() runs correctly but cannot emit.
the hello world page can emit.
and the socket listener works fine too.

if it helps, in bar(), I have the SID that the message needs to go to, and specifying that as a room does not work either. broadcast does not help either.

the emit in bar() does not throw an error with the current setup, but the message never gets delivered

I have also tried monkey patching but this does not help.

from python-socketio.

djpimp2010 avatar djpimp2010 commented on May 18, 2024

After more investigation, I realise that trying to emit out of context locks the socket from use. Once the thread tries to emit the first time, the messages from the HTTP route do not get delivered

from python-socketio.

djpimp2010 avatar djpimp2010 commented on May 18, 2024

Again, with more investigation, if I start the SocketIO app like below, then messages can be sent from within a thread (I believe its the async mode param),

socket = SocketIO(application, async_mode='gevent', ping_timeout=30, logger=False, engineio_logger=False)

However, sometimes the messages arent sent to the client instantly, until the server issues the "READING" statement in STDOUT.

If I start the SocketIO app with the ping_interval option set to 1, then it works faster - but I think this is wasting resources,.. Any ideas ?

from python-socketio.

miguelgrinberg avatar miguelgrinberg commented on May 18, 2024

@djpimp2010 you should be able to send events from a bg thread regarding of the async mode you use. In fact, the async mode is usually determined automatically by the extension based on the packages you have installed in your virtualenv, you do not need to specify it unless you want to override the defaults.

Assuming you are using eventlet or gevent, your background thread should be a greenlet, not a regular thread. If you monkey patched the python std library then the thread functions are automatically routed to the greenlet versions. In the thread, you cannot block for too long, if you have a long process you need to allow other greenlets to run by calling sleep(). When running in eventlet or gevent, multitasking is cooperative, so make sure you release the CPU to allow everything to run smoothly.

from python-socketio.

gordol avatar gordol commented on May 18, 2024

@prokher You don't have to use greenthreads, you can emit from a normal thread too, or even external processes. There is no inherent limitation there, am I wrong?

I'm 99% sure there are examples of this in the repo already, too (using normal threads).

Only the server needs greenthreads, not the workers!

from python-socketio.

gordol avatar gordol commented on May 18, 2024

@prokher after reading your message again, I think the confusion is that you're not understanding the message queue and how that facilitates communication between workers/servers/processes/threads/eventlets/etc.... The message queue functionality of the newer versions of python-socketio should allow any variety of configurations, for out-of-band emits.

from python-socketio.

gordol avatar gordol commented on May 18, 2024

Though if I'm wrong, someone please correct me... but this is my understanding of how this works, and we use this in production under considerable load and scale. :) Best of luck!

from python-socketio.

miguelgrinberg avatar miguelgrinberg commented on May 18, 2024

@prokher some comments on your note.

I think that the restriction that all threads must be greenthreads is too restrictive.

There is no such restriction. I personally don't think it is a good idea, but I don't think there is a problem with mixing green and regular threads in the same process. The green threads will obviously run all in the same physical thread context, but you can have additional threads if you want.

Consider you have a working thread which performs mathematical operation using numpy.

Putting heavy CPU tasks in a Python web server is a bad idea. Even if the GIL is released, I think you are looking for trouble. Much better to keep things separate by running one or a pool of workers for the CPU intensive tasks (for example using Celery). Then you are not bound to eventlet/gevent and can run those workers without any of the considerations required to run under these frameworks. As a benefit, you can scale the servers and the workers separately, since they may have different loads.

When math calculations finish I need to somehow notify the eventloop where socket io server lives in

These days this Socket.IO server supports multiple server nodes, and also emitting from non-server processes (such as these CPU intensive workers I proposed above). So this isn't really a problem. The only requirement to have these multi-process features is to run a message queue such as RabbitMQ or Redis that all these processes use to coordinate efforts.

from python-socketio.

miguelgrinberg avatar miguelgrinberg commented on May 18, 2024

My point is there could be quite normal use-cases when developer desires to send a message to socket.io client from a separate (not eventloop) thread.

I don't see this request as Socket.IO specific. Basically you are asking to support communication across system threads for eventlet/gevent, which might be already possible, I haven't really looked into it. Though its application is going to be severely limited, since you would want to only run code that doesn't lock the GIL on that other thread.

Just to make my point clear I mentioned Tornado server implementation

I think a solution for your problem should not be implement here, I see it as a request for eventlet or gevent. But note that async programming with callbacks like your Tornado example is a completely different paradigm than what these frameworks propose. I suppose with greenlets this could work as follows:

def my_greenlet():
    result = start_system_thread(my_thread_function, my_args)
    emit('result', data=result)

So the start_system_thread() function would go to sleep until the other thread ends. As I said above, it may be possible to implement this, it depends on having a way for another thread to send a signal to the thread running the greenlets, while the signal itself is greenlet aware. And a big unknown on how this might affect performance due to the GIL.

from python-socketio.

prokher avatar prokher commented on May 18, 2024

Dear @miguelgrinberg, you are right, my request is not socket.io-specific. It must be done in the underlying eventlet/gevent. I just found out tpool think in the eventlet documentation here http://eventlet.net/doc/threading.html it looks promising, we will try this asap.

from python-socketio.

miguelgrinberg avatar miguelgrinberg commented on May 18, 2024

@prokher ah, that actually looks pretty good. Very close to my example above!

from python-socketio.

prokher avatar prokher commented on May 18, 2024

Dear @gordol you are right, using soket.io client in the worker thread is possible solution which is much better than one with sleep method invocation.

But comparing to tpool-based approach I was not sure which one is better: using Socket.IO client from the working thread or using eventlet's tpool to start "signal waiting" thread. The former will use sockets for inner-process communication which is strange; the latter requires using dummy threads to wait for signal, using thread synchronization primitives and direct work with eventlet API. In terms of scalability and uniformity the solution to use Socket.IO client in the working thread is clearly better, I though about it before, but now, after discussing this issue with you, I think it is a way to go with as little kludges in the code as possible. Thank you all for this meaningful dialogue.

from python-socketio.

gordol avatar gordol commented on May 18, 2024

@prokher, indeed using native threading would definitely lead to higher performance, and perhaps there is something to be said about premature observation... But it sounds like you're not pushing lots of data, but more-so are doing lots of computation. It truly does depend on the workload and tasks at hand, and how one wishes to scale.

Best of luck!

from python-socketio.

gordol avatar gordol commented on May 18, 2024

Premature optimization, rather. Sorry I'm traveling today and typing from my phone. :) Anyway, the biggest factor, to me, would be memory usage, when using sockets for communication between threads. If your workload is memory intensive, especially on a desktop application, do please be mindful that sockets can lead to a bit of data duplication in memory.

from python-socketio.

gordol avatar gordol commented on May 18, 2024

Though that duplication should only be temporary I think! Wheeee!

from python-socketio.

jvrobert avatar jvrobert commented on May 18, 2024

I wrestled with this and read through all these replies for a long while and finally came up with a (probably not the best) solution. I needed threads because my web client makes a bunch of little AJAX calls in parallel and I am using Flask and didn't want to fiddle with figuring out the event soup. So I'm using uwsgi with threading for Flask.

So I just wrote a little middleware wrapper, so I run my Flask app in threads and it sends an 'emit' HTTP call to the same eventlet wsgi server that's serving out socket.io.

So I just do a post to serialize the message to the right thread. Flask is on port XXXX and this listens on portYYYY.

Would be awesome if I could just somehow do sio.emit() from any thread, though...

sio = socketio.Server(async_mode='eventlet')
class Middleware:
    def __init__(self, app):
        self.wrapped_app = app

    def __call__(self, environ, start_response):
        if environ['REQUEST_METHOD'] == 'POST' and environ['PATH_INFO'].startswith('/emit'):
            try:
                length = int(environ.get('CONTENT_LENGTH', '0'))
            except ValueError:
                length = 0
            if length != 0:
                body = environ['wsgi.input'].read(length)
                obj = json.loads(body.decode('utf-8'))
                if 'message' in obj and 'body' in obj:
                    sio.emit(obj['message'], obj['body'])
            status = '200 OK'
            response_headers = [('Content-type', 'text/plain')]
            start_response(status, response_headers)
            return ['OK']
        return self.wrapped_app(environ, start_response)

wsapp = socketio.Middleware(sio)
wsapp = Middleware(wsapp)
...
def ws_server():
    eventlet.wsgi.server(eventlet.listen(('', port)), wsapp)

ws_thread = threading.Thread(target=ws_server)
ws_thread.daemon = True
ws_thread.start()

from python-socketio.

miguelgrinberg avatar miguelgrinberg commented on May 18, 2024

I needed threads because my web client makes a bunch of little AJAX calls in parallel and I am using Flask and didn't want to fiddle with figuring out the event soup.

The green threads from eventlet are perfect for this use case. Did you know? Just monkey patch the Python standard library, then use your threads as you normally do, and eventlet switches them up for greenlets.

Your example is limited. For example, there is no easy way to implement callbacks. Implementing sending messages to specific users, or to a room would not be as hard, but you don't have support for that in the code above.

If you want to go the two server route, I recommend you use two physically separate servers, one for Flask, one for Flask-SocketIO, then use the message queue support already in the extension to be able to emit from the Flask side. This has full support for all the SocketIO features.

Would be awesome if I could just somehow do sio.emit() from any thread, though...

I haven't really seen a strong use case to support this option. If you are using eventlets, and your threads are green threads, this works just fine. The only case that is not supported is the hybrid application with green and regular threads mixed up.

from python-socketio.

jvrobert avatar jvrobert commented on May 18, 2024

Thanks Miguel - appreciate the feedback (and the great library). I did do some quick testing with just using pure green threads but it seemed to run through my ajax calls more or less sequentially. I am doing file IO on each call, maybe that's why?

I will play around with the message queue support and two separate processes.

from python-socketio.

miguelgrinberg avatar miguelgrinberg commented on May 18, 2024

@jvrobert File I/O is not something that can be made async, because the OS support is not at all consistent between platforms. Windows (of all things!) has pretty good support for async file I/O, but Linux is kind of a mess, there isn't a good way to do it, unfortunately. The commonly accepted method of doing async I/O in Linux is to use a thread pool.

So I have to modify my advice above to accommodate for this requirement. Instead of using all green threads, you can use an Eventlet thread pool to offload the file operations to physical threads, while keeping everything else in the green thread domain. Basically this thread pool from eventlet allows you to run a blocking operation in a separate thread, without blocking the main thread with all the greenlets.

from python-socketio.

18o avatar 18o commented on May 18, 2024

use socket.start_background_task

from python-socketio.

ageir avatar ageir commented on May 18, 2024

Oooooops.. Sorry for posting this in the wrong place!! My bad!
Found the error myself, edited my post.

You can delete my posts if you don't want them here
Sorry again for not reading properly where i was posting.

Thanks for clarifying the difference between emit and socketio.emit. Kudos!

from python-socketio.

shashank-bhatt-07 avatar shashank-bhatt-07 commented on May 18, 2024

@miguelgrinberg, if i need to only send the message to one client in socketio.emit(), how will I do that?

from python-socketio.

miguelgrinberg avatar miguelgrinberg commented on May 18, 2024

You need to add room=sid to the emit() call. The sid value represents the client you want to address. You receive this value in the connect and other events the client sends to the server.

from python-socketio.

shashank-bhatt-07 avatar shashank-bhatt-07 commented on May 18, 2024

Thanks @miguelgrinberg
This is what I am doing in another file, not in the file socketio is defined -

from flask import request
room = request.sid

Is it a correct way to get sid?
Also In this file I have created a start_background_task with a function having while True loop which start only on a specific value from client not directly.

when I am using async = eventlet, sometimes message goes from server to client but not always.
In addition to this client automatically gets disconnected and again connects. why?(I think just for eventlet case this happens)

But when client disconnect, this start_background_task doesn't stop. Why is it like this?

Thanks for the help.

from python-socketio.

miguelgrinberg avatar miguelgrinberg commented on May 18, 2024

request.sid will give you the sid of the client that sent the event you are currently handling. If you want to target arbitrary clients when you send an event, you have to store these sid values and associate them with your users. A good place to do that is the connect event handler.

from python-socketio.

miguelgrinberg avatar miguelgrinberg commented on May 18, 2024

@shashankbhatt regarding your timeouts, what version of python-engineio are you using? I have been making some improvements on that area recently, try the latest release.

from python-socketio.

shashank-bhatt-07 avatar shashank-bhatt-07 commented on May 18, 2024

I am using Python 2.7.13.

Eventlet version is 0.21.0 and flask socketio version is 2.8.6.

I need to use this for production where my webserver will run using gunicorn. what are your thoughts on using websockets in Node.js for webserver instead. (Although I dont want to use it.)

Is it better than flask socketio from scalability perspective ?

Thanks

from python-socketio.

miguelgrinberg avatar miguelgrinberg commented on May 18, 2024

@shashankbhatt as I said above, the package you need to update is one of the dependencies of flask-socketio. Make sure you have python-engineio at 1.5.2, which is the latest release.

As far as node vs python for Socket.IO, that's really a difficult comparison. Node is a much faster language than python, so really if your only criteria is performance, you would not choose Python over Node/JavaScript for anything.

from python-socketio.

shashank-bhatt-07 avatar shashank-bhatt-07 commented on May 18, 2024

Thanks @miguelgrinberg now I see..but even though I have updated python-engineio still problem with eventlet remains the same...(client disconnect and not able to emit from another thread to client)

Even I got a log also saying "can't switch to another thread" for eventlet switch. Why is this happening in case of eventlet only that client automatically disconnects? for gevent and threading its working fine.

from python-socketio.

miguelgrinberg avatar miguelgrinberg commented on May 18, 2024

Where do you get the "can't switch" error? Do you have a stack trace?

from python-socketio.

shashank-bhatt-07 avatar shashank-bhatt-07 commented on May 18, 2024

In cmd(server logs) I saw this on the point when I was creating another thread...Although thread got started.

I think when I am using eventlet I cannot start a thread rather I should do eventlet.spawn.

from python-socketio.

miguelgrinberg avatar miguelgrinberg commented on May 18, 2024

@shashankbhatt yes, of course. Threads, sockets, anything else that is blocking are bound to give you problems when used alongside eventlet. But if you monkey patch the standard library, then all those classes and functions are replaced with equivalent versions that are eventlet friendly.

from python-socketio.

shashank-bhatt-07 avatar shashank-bhatt-07 commented on May 18, 2024

Yes @miguelgrinberg Now I think I should use threading and spawn a gevent greenlet rather than thread...

This way I can save resources I guess...because for 1000 request I am creating 2000 threads(one per request and within that another one). If I will spawn a greenlet I will save creating 1000 more threads.

from python-socketio.

quantumproducer avatar quantumproducer commented on May 18, 2024

+1

from python-socketio.

ahmed-alhaj1 avatar ahmed-alhaj1 commented on May 18, 2024
  • Restarting with stat
  • Debugger is active!
  • Debugger PIN: 304-783-885
    (14228) wsgi starting up on http://127.0.0.1:5000
    (14228) accepted ('127.0.0.1', 51258)
    127.0.0.1 - - [05/Aug/2018 21:25:46] "GET /socket.io/?EIO=3&transport=polling&t=1533518746862-143 HTTP/1.1" 200 381 0.000530
    message handler error
    Traceback (most recent call last):
    File "/home/alhaj1/fenv/local/lib/python2.7/site-packages/engineio/server.py", line 411, in _trigger_event
    return self.handlersevent
    File "/home/alhaj1/fenv/local/lib/python2.7/site-packages/socketio/server.py", line 516, in _handle_eio_message
    pkt = packet.Packet(encoded_packet=data)
    File "/home/alhaj1/fenv/local/lib/python2.7/site-packages/socketio/packet.py", line 43, in init
    self.attachment_count = self.decode(encoded_packet)
    File "/home/alhaj1/fenv/local/lib/python2.7/site-packages/socketio/packet.py", line 113, in decode
    self.data = self.json.loads(ep)
    File "/usr/lib/python2.7/json/init.py", line 339, in loads
    return _default_decoder.decode(s)
    File "/usr/lib/python2.7/json/decoder.py", line 364, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
    File "/usr/lib/python2.7/json/decoder.py", line 382, in raw_decode
    raise ValueError("No JSON object could be decoded")
    ValueError: No JSON object could be decoded
    127.0.0.1 - - [05/Aug/2018 21:25:46] "POST /socket.io/?EIO=3&transport=polling&t=1533518746865-144&sid=4c63da76410e43deac9f46e415f83a4d HTTP/1.1" 200 219 0.000908
    (14228) accepted ('127.0.0.1', 51260)
    (14228) accepted ('127.0.0.1', 51262)
    127.0.0.1 - - [05/Aug/2018 21:25:46] "GET /socket.io/?EIO=3&transport=polling&t=1533518746866-145&sid=4c63da76410e43deac9f46e415f83a4d HTTP/1.1" 200 215 0.000437

from python-socketio.

ahmed-alhaj1 avatar ahmed-alhaj1 commented on May 18, 2024

server side

from future import print_function
import os
from flask import Flask, render_template, request, send_from_directory
from flask_socketio import SocketIO
import json as js

app = Flask(name)
#json_str = json_str.encode('latin-1').decode('utf-8')
socketio = SocketIO(app, async_mode='eventlet')
basedir = os.path.abspath(os.path.dirname(file))

app.config['SECURITY_KEY'] = 'secret'
app.config['DEBUG'] = True
app.config['ALLOWED_EXTENSIONS'] = set(["pdf", "docx", "doc"])

@app.route('/')
def show_file():
return render_template("display.html")

@socketio.on_error() # Handles the default namespace
def error_handler(e):
pass

@socketio.on('json')
def handle_message(json_str):

json_str = json_str.encode('latin-1').decode('utf-8')
print( json_str)

if name == 'main':
socketio.run(app)

client side

<script type="text/javascript" src="//code.jquery.com/jquery-2.1.3.min.js"></script> <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/socket.io/1.3.6/socket.io.min.js"></script> <script type="text/javascript" charset="utf-8"> var namespace = "/" var data = "name its connected"; //var data= "Hellow world woooooooooooooow"; var socket = io.connect('http://' + location.host + ':' + location.port ); socket.on('connect', function() { socket.emit('client_connected',{'data':'you are connected!'}); }); </script>

from python-socketio.

gordol avatar gordol commented on May 18, 2024

that log is useless without context or code

from python-socketio.

gordol avatar gordol commented on May 18, 2024

why are you emitting from a connect callback in the frontend?

what does this have to do with the discussion? you are using eventlet, not background threads.

also your code is wrong, you need to read the docs. you shouldn't be handing json that way. it's already decoded via request context.

this has nothing to do with the thread you posted in.

from python-socketio.

mvelebit avatar mvelebit commented on May 18, 2024

@gordol He missed the repo, that callback emit is from the flask-socketio docs..

from python-socketio.

nimishbansal avatar nimishbansal commented on May 18, 2024

according to this #16 (comment)
How to do that in django and where should be the eventlet.monkeypatch() be called in django?

from python-socketio.

miguelgrinberg avatar miguelgrinberg commented on May 18, 2024

@nimishbansal I would add monkey patching in manage.py and wsgi.py both to cover all usages.

from python-socketio.

nimishbansal avatar nimishbansal commented on May 18, 2024

@miguelgrinberg and what about emitting how should I emit that?
eventlet.spawn(fun) or socket.start_background_task()

I tried a lot of several combinations but no result. I tried adding monkey patching in manage.py and wsgi.py but it doesn't solved it.

Also I am using gunicorn so I believe in manage.py it won't be necessary.
After so many doubts I landed at stackoverflow with this question.
eventlet-with-django-and-python-socket-io.
Could you please help me out. I have just stuck here.

My Server emit works only when the client gets connected(in that case emit of both client and server works perfectly), but it doesn't work when server emits event itself to the client.

from python-socketio.

nimishbansal avatar nimishbansal commented on May 18, 2024

Thanks, it is resolved now. The biggest blunder that I made was that two different processes were running. Out of which socket server was running at 5000 but I was continuously emitting from port 8000
. The last comment in this issue made me realize to check the process id, and I founded out that they were different. So I changed to emit from 5000 only.
Thanks for the help.

from python-socketio.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.