This post is about creating Python Flask web pages that can be asynchronously updated by your Python Flask application at any point without any user interaction. We’ll be using Python Flask, and the Flask-SocketIO plug-in to achieve this. In short, the final result is hosted on GitHub.

What I want to achieve here is a web page that is automatically updated for each user as a result of events that happened in the background on my server system. For example, allowing events like a continually updating message stream, a notification system, or a specific Twitter monitor / display. In this post, I show how to develop a bare-bones Python Flask application that updates connected clients with random numbers. Flask is an extremely lightweight and simple framework for building web applications using Python.

Flask logo

If you haven’t used Flask before, it’s amazingly simple, and to get started serving a very simple webpage only requires a few lines of Python:

Running this file with  python application.py will start a server on your local machine with one page saying “Hello World!” A quick look through the documentation and the first few sections of the brilliant mega-tutorial by Miguel Grinberg will have you creating multi-page python-based web applications in no time. However, most of the tutorials out there focus on the production of non-dynamic pages that load on first accessed and don’t describe further updates.

For the purpose of updating the page once our user has first visited, we will be using Socket.io and the accomanying Flask addon built by the same Miguel Grinberg, Flask-Socketio (Miguel appears to be some sort of Python Flask God). Socket IO is a genius engine that allows real-time bidirectional event-based communication. Gone are the days of static HTML pages that load when you visit; with Socket technology, the server can continuously update your view with new information.

For Socket.io communication, “events” are triggered by either the server or connected clients, and corresponding callback functions are set to execute when these events are detected. Implementing event triggers or binding event callbacks are very simply implemented in Flask (after some initial setup) using:

Four events are allowed in the @socketio.on() decorator – ‘connect’, ‘disconnect’, ‘message’, and ‘json’. Namespaces can also be assigned to keep things neatly separated, and the send() or emit() functions can be  used to send ‘message’ or custom events respectively – see the details on Miguel’s page.

On the client side, a little bit of JavaScript wizardry with jQuery is used to handle incoming and trigger outgoing events. I would really recommend the JavaScript path on CodeSchool if you are not familiar with these technologies.

And that, effectively, is the bones of sending messages between client and server. In this specific example, we want the server to be continually working in the background generating new information, while at the same time allowing new clients to connect, and pushing new information to connected clients. For this purpose, we’ll be using the Python threading module to create a thread that generates random numbers regularly, and emits the newest value to all connected clients. Hence, in application.py, we define a thread object that will continually create random numbers and emit them using socketIO separately to the main flask process:

In our main Flask code then, we start this RandomThead running, and then catch the emitted numbers in Javascript on the client. Client presentation is done, for this example, using a simple bootstrap themed page contained in the Flask Template folder, and the number handling logic is maintained in the static JavaScript file application.js. A running list of 10 numbers is maintained and all connected clients will update simultaneously as new numbers are generated by the server.

And in the application.py file:

And that’s the job. Flask served web pages that react to events on the server. I was tempted to add a little graph using HighCharts or AmCharts, but I’m afraid time got the better of me. Perhaps in part2. The final output should look like this:

Flask screenshot

You can find all of the source code on GitHub, with instructions on how to install the necessary libraries etc. Feel free to adapt to your own needs, and leave any comments if you come up with something neat or have any problems. This functionality is documented in the original documentation for Flask-SocketIO. The documentation and tutorials are quite comprehensive and worth working through if you are interested in more.

  1. Hi,

    Why is it only within the console are the random numbers being generated, but nothing on the browser after

    Number list:

    Thanks much appreciated.

    Seb

  2. Hi,
    Thanks for this tutorial, I downloaded your code, run it but got this :

    (flaskiotest) C:\Users\alotfi\PycharmProjects\async_flask-master>python application.py
    WebSocket transport not available. Install eventlet or gevent and gevent-websocket for improved performance.
    * Running on http://127.0.0.1:5000/
    * Restarting with reloader
    WebSocket transport not available. Install eventlet or gevent and gevent-websocket for improved performance.

    Thanks, your help is appreciated.

    • Hi guys, I think some version issues are affecting this. Can you try putting in the following code and see if it works at the top of the file:

      import eventlet
      eventlet.monkey_patch()

  3. Hi guys,
    download the jquery and socketio files and put this in static directory.
    change this code in the head:

    change this:
    import eventlet
    eventlet.monkey_patch()
    from flask_socketio import SocketIO, emit

    and this:

    #turn the flask app into a socketio app
    async_mode = “eventlet”

    socketio = SocketIO(app, async_mode=async_mode)

    and it works

  4. I also can’t find a python module called eventlet. And, monkey.py appears to be in the gevent module. No sign of the monkey_patch() in gevent.

  5. My bad, I found the eventlet module and applied this to the application.py:
    import eventlet
    eventlet.monkey_patch()

    It works without adding this:
    async_mode = “eventlet”

    socketio = SocketIO(app, async_mode=async_mode)

    It also works when it is added…

    BTW: I updated the index.html file to:

    also modified the print statements to Python 3 style.

    So, I can report it now works in python 3.5.2.

Leave a Reply