NOTE: Don’t directly change your production server with Robyn web framework. The user’s discretion is advised.
Have you heard of this new gossip spreading in GitHub town!!! There is a newborn web framework that came into the town and recently it is getting a lot of popularity because of its cool features and async compatibility and its fast processing as it is built on Rust.
The author of the Robyn web framework Sanskar Jethi started this project on 22nd May 2021. Let’s first talk about some of its features
Features
- Underactive development!
- Written in Rust, btw xD
- A multithreaded Runtime
- Extensible
- A simple API
- Sync and Async Function Support
- Dynamic URL Routing
- Multi-Core Scaling
- WebSocket!
- Hot Reloading (Still experimental)
- Query Params
- Events (Startup and Shutdown)
- Community First and truly FOSS!
Usage
pip install robyn
To start a server with a single super useful API of hello world
from robyn import Robyn
app = Robyn(__file__)
@app.get("/")
async def hellow_world():
return "Hello, world!"
app.start(port=5000)
Now just run the file with the python command
python main.py
You can see the output in the terminal below
But after a while, the logs will be flooded by the below message. But it’s not a big deal, I’m also thinking to contribute in this cool project.
There is also a hot reloading feature but it’s in beta version as mentioned by the contributors. You can enable it using the below command
python main.py --dev
Somehow quitting the framework is not as smooth as I thought. It left some dangling processes alive on the port once it exited.
Writing API requests is very easy and the same as Flask 2.0
GET Request
@app.get("/")
async def h(request):
return "Hello World"
POST Request
@app.post("/post")
async def postreq(request):
return bytearray(request["body"]).decode("utf-8")
PUT Request
@app.put("/put")
async def postreq(request):
return bytearray(request["body"]).decode("utf-8")
PATCH Request
@app.patch("/patch")
async def postreq(request):
return bytearray(request["body"]).decode("utf-8")
DELETE Request
@app.delete("/delete")
async def postreq(request):
return bytearray(request["body"]).decode("utf-8")
Having Dynamic Routes
You can add params in the routes and access them from the request object.
@app.post("/jsonify/:id")
async def json(request):
print(request["params"]["id"])
return jsonify({"hello": "world"})
Some of the features are exactly like Flask. If you want to get JSON data then you can use the Jsonify function of Robyn web framework
from robyn import jsonify @app.post("/jsonify")
async def json(request):
print(request)
return jsonify({"hello": "world"})
Websockets
Robyn web framework is also having an outbox solution for WebSocket in it. This feature really impressed me. You can now serve WebSockets using Robyn. Firstly, you need to create a WebSocket Class and wrap it around your Robyn app.
from robyn import Robyn, static_file, jsonify, WS
app = Robyn(__file__)
websocket = WS(app, "/web_socket")
Now, you can define 3 methods for every web_socket for their life cycle, they are as follows:
@websocket.on("message")
def connect():
global i
i+=1
if i==0:
return "Whaaat??"
elif i==1:
return "Whooo??"
elif i==2:
return "*chika* *chika* Slim Shady."
elif i==3:
i= -1
return ""@websocket.on("close")
def close():
return "Goodbye world, from ws"@websocket.on("connect")
def message():
return "Hello world, from ws"
The three methods:
- “message” is called when the socket receives a message
- “close” is called when the socket is disconnected
- “connect” is called when the socket connects
Usage
@websocket.on("message")
async def connect():
global i
i+=1
if i==0:
return "Whaaat??"
elif i==1:
return "Whooo??"
elif i==2:
return "*chika* *chika* Slim Shady."
elif i==3:
i= -1
return ""@websocket.on("close")
async def close():
return "Goodbye world, from ws"@websocket.on("connect")
async def message():
return "Hello world, from ws"
Performance comparison across different frameworks
I am pasting the following comparison that is done by the author of Robyn web framework on his development machine.
I used oha to perform the testing of 10000 requests on the following frameworks and the results were as follows
Flask(Gunicorn)
Total: 5.5254 secs
Slowest: 0.0784 secs
Fastest: 0.0028 secs
Average: 0.0275 secs
Requests/sec: 1809.8082
FastAPI(Uvicorn)
Total: 4.1314 secs
Slowest: 0.0733 secs
Fastest: 0.0027 secs
Average: 0.0206 secs
Requests/sec: 2420.4851
Django(Gunicorn)
Total: 13.5070 secs
Slowest: 0.3635 secs
Fastest: 0.0249 secs
Average: 0.0674 secs
Requests/sec: 740.3558
Robyn(Doesn’t need a *SGI)
Total: 1.8324 secs
Slowest: 0.0269 secs
Fastest: 0.0024 secs
Average: 0.0091 secs
Requests/sec: 5457.2339
Robyn (5 workers)
Total: 1.5592 secs
Slowest: 0.0211 secs
Fastest: 0.0017 secs
Average: 0.0078 secs
Requests/sec: 6413.6480
Robyn web framework is able to serve the 10k requests in 1.8 seconds followed by Flask and FastAPI, which take around 5 seconds(using 5 workers on a dual-core machine). Finally, Django takes around 13.5070 seconds.
Conclusion
If you liked this story. Then you can buy me a coffee using this link. That will motivate me to write more blogs like this. Peace out.