Making plots in your terminal with plotext

By on 22 August 2022

In this blog post a quick script to plot the frequency of our blog articles in the terminal. It’s good to see that we’re getting back on track 🙂

The code gist is here.

First we import the libraries we are going to use. As always we separate Standard Library modules from 3rd party ones as per PEP8:


from collections import Counter
from datetime import date

from dateutil.parser import parse
import plotext as plt
import requests

Then I define some constants:

API_URL = "https://codechalleng.es/api/articles/"
START_YEAR = 2017
THIS_YEAR = date.today().year
THIS_MONTH = date.today().month
MONTH_RANGE = range(1, 13)

I defined a year month generator. Why? Because some months we have not posted, yet I still want to show them on the graph.

def _create_yymm_range():
    for year in range(START_YEAR, THIS_YEAR + 1):
        for month in MONTH_RANGE:
            yield f"{year}-{str(month).zfill(2)}"
            if year == THIS_YEAR and month == THIS_MONTH:
                break

Then the wokhorse function that calculates the amount of posts per month. We conveniently use a Counter, the right abstraction here:

def get_articles_per_month(url=API_URL):
    ym_range = _create_yymm_range()
    cnt = Counter({ym: 0 for ym in ym_range})
    data = requests.get(API_URL)
    for row in data.json():
        dt = parse(row["publish_date"])
        if dt.year < START_YEAR:
            continue
        ym = dt.strftime("%Y-%m")
        cnt[ym] += 1
    return cnt

We use the requests library to get all the articles which we expose using our platform’s API.

Again, using _create_yymm_range() we make sure that all months are covered, even if there were 0 posts.

(Looking back cnt could be better named as number_posts_per_months. Well, you hardly get it right the first time!)

Making a plot with plotext is as simple as picking the type of graph and feeding it labels and values:

def show_plot(data):
    labels, values = zip(*data.items())
    plt.bar(labels, values)
    plt.title("Pybites articles published per month")
    plt.show()

zip(*data.items()) is a nice trick to extract labels and values from a list of tuples (which a dict’s .items() method gives us):

>>> d = {1: 'a', 2: 'b', 3: 'c'}
>>> list(zip(*d.items()))
[(1, 2, 3), ('a', 'b', 'c')]

We give the plot a title and show it, which will render it in the terminal.

Lastly we make sure we call the two functions only if you call the script directly, not when importing it.

You do that by using an if __name__ == "__main__" block:

if __name__ == "__main__":
    data = get_articles_per_month()
    show_plot(data)

And the result:

Screenshot 2022 08 19 at 14.33.29
Pybites # of blog posts per month since we started.

 —

Thanks Russell for introducing me to this library the other day. Do you want to see a really cool use case? Check out his blog article 😍

Want a career as a Python Developer but not sure where to start?