title: Running flask-socketio in thread
body: <p>I have an interactive Python application where I also want to use flask-socketio to interface with Javascript clients.
  Hence, I need Python socketio to run as a thread.</p>
  
  <p><strong>Approach #1:</strong></p>
  
  <pre><code>def socketio_server_fn():
      socketio.run(flask_app, port=5000)
  flask_app = Flask(__name__)
  socketio = flask_socketio.SocketIO(flask_app, always_connect=True, async_mode='threading')
  socketio_thread = socketio.start_background_task(socketio_server_fn)
  </code></pre>
  
  <p>Problem 1.1: It doesn't use the Websocket transport as that's not compatible with standard Python threads. Instead, socketio falls back to polling.</p>
  
  <p>Problem 1.2: Polling is not only inefficient but also spams the console with messages such as these every second:</p>
  
  <blockquote>
    <p>127.0.0.1 - - [10/Oct/2019 13:57:11] "GET /socket.io/?EIO=3&amp;transport=polling&amp;t=MsrXwsJ&amp;sid=c63dfaefdbb84c688dd53bef2f6d3c77 HTTP/1.1" 200 -</p>
  </blockquote>
  
  <p>I haven't been able to remove these messages and others have had very mixed results too: <a href="https://stackoverflow.com/questions/14888799/disable-console-messages-in-flask-server">Disable console messages in Flask server</a></p>
  
  <p><strong>Approach #2: Use eventlet</strong></p>
  
  <p>First we need to patch the Python threading system at the start of the program:</p>
  
  <pre><code>import eventlet
  eventlet.monkey_patch()
  </code></pre>
  
  <p>And then change the SocketIO object creation line to:</p>
  
  <pre><code>socketio = flask_socketio.SocketIO(flask_app, always_connect=True, async_mode='eventlet')
  </code></pre>
  
  <p>Now socketio uses Websocket.</p>
  
  <p>Problem 2.1: I would prefer to avoid monkey_patch for the whole Python threading system.</p>
  
  <p>Problem 2.2: Using eventlet seems to break socketio.stop() when tearing down the application. stop() now hangs even when called from a HTTP handler function. The same teardown code worked with both async_mode='threading' and using normal socketio.run(). socketio.server.stop() also hangs.</p>
  
  <p>Problem 2.3: Eventlet doesn't seem fully compatible with prompt_toolkit:</p>
  
  <pre><code>Exception in default exception handler
  Traceback (most recent call last):
    File "python\lib\site-packages\prompt_toolkit\eventloop\win32.py", line 102, in _run_task
      t()
    File "python\lib\site-packages\prompt_toolkit\eventloop\context.py", line 116, in new_func
      return func(*a, **kw)
    File "python\lib\site-packages\prompt_toolkit\patch_stdout.py", line 103, in write_and_flush_in_loop
      run_in_terminal(write_and_flush, in_executor=False)
    File "python\lib\site-packages\prompt_toolkit\application\run_in_terminal.py", line 50, in run_in_terminal
      return run_coroutine_in_terminal(async_func, render_cli_done=render_cli_done)
    File "python\lib\site-packages\prompt_toolkit\application\run_in_terminal.py", line 71, in run_coroutine_in_terminal
      assert app._is_running
  AssertionError
  </code></pre>
  
  <p><strong>Approach #3: Using gevent</strong>
  This doesn't seem to work at all.</p>
  
  <p>Isn't there an easy solution to the seemingly common use case of running flask-socketio as a thread?</p>