DEV Community

Cover image for Bocadillo: Yet Another Python Framework
Itachi Uchiha
Itachi Uchiha

Posted on

Bocadillo: Yet Another Python Framework

Hi everyone. In this post, I'll introduce the Bocadillo framework. As you know, there are a lot of web frameworks in Python.

In the past days, I was looking for new technologies to improve myself. I saw Bocadillo on GitHub.

What is Bocadillo?

Bocadillo is a modern Python web framework filled with asynchronous salsa.

You can access Bocadillo's website using this link: https://bocadilloproject.github.io/

You can find Bocadillo on GitHub: https://github.com/bocadilloproject/bocadillo

Its key features are;

  • Productive
  • Real-time capable
  • Flexible
  • Performant
  • Empowering
  • Transparent

Transparent: All codes are developed with type-annotation.

You can also develop WebSocket apps. Actually, I think, its big claim is WebSockets.

Installation

The Bocadillo has a CLI tool to create projects. But you don't need to install the CLI tool.

CLI Installation

pip install bocadillo-cli
Enter fullscreen mode Exit fullscreen mode

Framework Installation

pip install bocadillo
Enter fullscreen mode Exit fullscreen mode

Using virtualenv

mkdir my_first_app

cd my_first_app

virtualenv .

source bin/activate

pip install bocadillo
Enter fullscreen mode Exit fullscreen mode

Now, we installed the Bocadillo.

First Bocadillo App

You can use favorite editor or IDE. I'll create a file called app.py

touch app.py
Enter fullscreen mode Exit fullscreen mode

I'll edit app.py file with the nano editor. Yes this is hippie style :)

# app.py file
from bocadillo import App

app = App()

@app.route("/")
async def index(req, res):
  res.text = "Hello Dev Family"
Enter fullscreen mode Exit fullscreen mode

That's all. Bocadillo highly similar to the Flask framework. To run our first app, we'll use the uvicorn.

Don't worry it comes up with the Bocadillo. You don't need to install it again.

uvicorn app:app --reload

We'll run our first application using the above command. After this command you'll see an output like below;

INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO: Started reloader process [24076]
INFO: Started server process [24078]
INFO: Waiting for application startup.
INFO: ASGI 'lifespan' protocol appears unsupported.
Enter fullscreen mode Exit fullscreen mode

This means, our web app works on port 8000. Good work, we created our first app. Let's change our app and use background tasks.

from asyncio import sleep
from bocadillo import App

app = App()

@app.route("/")
async def index(req, res):

  try:
    if req.query_params["wait"] == "true":
      @res.background
      async def waitForTest():
        await sleep(15)
        print("I'll work :)")
  except:
    print(":/")

  res.text = "Hello Dev family"
Enter fullscreen mode Exit fullscreen mode

Background tasks are a lightweight mechanism to perform processing after a request has been sent, without making the client wait for the result. Typical examples include sending email, or sending logs to a remote system.

When registered on the Response, the background task won't run immediately. Instead, the view will terminate as usual, and the response will be sent. Only then, the background task will execute.

This prevents clients from waiting for the background task to finish before getting a response.*

If you try without background tasks, you need to wait for the sleep method finish. Firstly you should try the above code.

1-) Open two terminals.

Run this command in the first terminal.

curl http://127.0.0.1:8000/?wait=true

Immediately run this command in the second terminal.

curl http://127.0.0.1:8000/

You'll see "Hello Dev family" output in all terminals. You need also look at the original terminal which you run your first app.

After 15 seconds, you'll see "I'll work" output.

If you don't use async background tasks you will need to wait for the sleep method finish.

import time
from bocadillo import App

app = App()

@app.route("/")
async def index(req, res):

  try:
    if req.query_params["wait"] == "true":
      time.sleep(15)
      print("I'll work :)")
  except:
    print(":/")

  res.text = "Hello Dev family"
Enter fullscreen mode Exit fullscreen mode

Don't forget, Background tasks must be non-blocking.. Because a background task is a coroutine, it must be non-blocking to avoid blocking the main thread and preventing requests from being processed.

That's all for now.

You should look at the Bocadillo Guide for the other features. I introduced the Bocadillo.

Guide: https://bocadilloproject.github.io/guide/

Thanks for reading.

Top comments (10)

Collapse
 
anortef profile image
Adrián Norte

Dude, I do not what I'm gonna do with it but I need to use this framework.

Collapse
 
itachiuchiha profile image
Itachi Uchiha

Hehe. Actually, you can use for web applications. Bocadillo is very similar to Flask.

You probably heard about the Flask framework. Using Bocadillo, you can create async web apps.

Collapse
 
crazy_prithvi profile image
Prithvi Sai Kavuri

doesnt flask support async apps?

Collapse
 
florimondmanca profile image
Florimond Manca • Edited

Maintainer of Bocadillo here! 👋

Thanks a lot for this post, @aligoren ! Very concise and nicely written. :-)

P.S.: the "ASGI 'lifespan' protocol appears unsupported." message you see when starting the Uvicorn server is because app.py is missing a small thing, i.e. a call to configure():

from bocadillo import App, configure

app = App()
configure(app)

This is documented here, if you're interested: Minimal working application

Thanks again for this article!

Collapse
 
itachiuchiha profile image
Itachi Uchiha

Hehe :)

Thanks. I actually knew that (ASGI lifespan message). I have a plan for Bocadillo. I'm thinking about a series. Maybe like Miguel Grinberg's Flask series.

I enjoyed with Bocadillo. Thanks <3 :)

Collapse
 
florimondmanca profile image
Florimond Manca

That would be awesome! If you need anything from me, my DMs are open, here or on Twitter. :)

Thread Thread
 
itachiuchiha profile image
Itachi Uchiha

Haha. Are you sure? I’ll be trouble :P

Collapse
 
fenchu profile image
fenchu

I need the following:

  • SSL proxy forwarding (Apache proxy with lets encrypt)
  • OAuth authentication with bearer tokens.
  • Swagger out of the box, or easy to configure without marshmallow(It is too strict)

This works perfectly in Flask.

If Bocadilly can document this I will give it a try :-)

Collapse
 
florimondmanca profile image
Florimond Manca

Thanks, this is very helpful!

We’ve been working on reusability so far, but I think built-in OpenAPI/Swagger support will be the next big thing. It’s been a very demanded feature!

As for OAuth (and other kinds of authentication), it’s also on the road map. In fact I’ve already begun working on authentication for ASGI apps here: starlette-auth-toolkit.

SSL proxy forwarding

You can serve a Bocadillo app with HTTPS using uvicorn/Gunicorn, and this is documented here: HTTPS. If you’re thinking of something else, let me know!

Collapse
 
jhermann profile image
Jürgen Hermann

Marked as unmaintained by now…