How to Create Stunning Graphs in the Terminal with Python

Sourav De
9 min readMay 14

--

Photo by Behnam Norouzi on Unsplash

A picture is worth thousand words

In today’s data-driven world, visualizations or graphs do express a story worth a thousand words. Visualizations provide quick and effective communication media to convey data which if shared with text or table might be difficult to comprehend.

While there are many powerful visualization tools available, sometimes we need a quick and easy way to visualize data directly in the terminal. Whether we’re working remotely, on a server, or just need to share a quick visualization with a colleague, the ability to plot graphs in the terminal can be incredibly useful.

Let’s see a simple example scenario, I am trying to find out the latency of AWS regions from my location. I got the data and want to compare it now:

data = [
{
"#": 1,
"AWS Region Name": "US East (N. Virginia)",
"Region Code": "us-east-1",
"Mean": "741 ms",
"Median": "730 ms",
"Min": "723 ms",
"Max": "780 ms",
},
{
"#": 2,
"AWS Region Name": "US East (Ohio)",
"Region Code": "us-east-2",
"Mean": "525 ms",
"Median": "530 ms",
"Min": "244 ms",
"Max": "797 ms",
},
{
"#": 3,
"AWS Region Name": "US West (N. California)",
"Region Code": "us-west-1",
"Mean": "540 ms",
"Median": "535 ms",
"Min": "270 ms",
"Max": "819 ms",
},
{
"#": 4,
"AWS Region Name": "US West (Oregon)",
"Region Code": "us-west-2",
"Mean": "602 ms",
"Median": "594 ms",
"Min": "299 ms",
"Max": "923 ms",
},
{
"#": 5,
"AWS Region Name": "Africa (Cape Town)",
"Region Code": "af-south-1",
"Mean": "632 ms",
"Median": "627 ms",
"Min": "320 ms",
"Max": "953 ms",
},
{
"#": 6,
"AWS Region Name": "Asia Pacific (Melbourne)",
"Region Code": "ap-southeast-4",
"Mean": "599 ms",
"Median": "598 ms",
"Min": "296 ms",
"Max": "905 ms",
},
{
"#": 7,
"AWS Region Name": "Asia Pacific (Hong Kong)",
"Region Code": "ap-east-1",
"Mean": "362 ms",
"Median": "361 ms",
"Min": "353 ms",
"Max": "374 ms",
},
]

print("\nAWS Ping Test results: ")
print("=========================")
for d in data:
print(d["Region Code"], "\t", d["Mean"])


print("\nAWS Ping Test results: ")
print("=========================")
for d in data:
ms = int(d["Mean"].replace(" ms", ""))
ms_bar = round(ms / 10)
print(d["Region Code"], "\t", "*" * ms_bar)

The output is the following:

If we take a quick look although both the tables give us similar info but it’s easy to find the lowest latency in the bar graph. From this quick demonstration, we can actually see the usefulness of such CLI visualizations.

Now in some cases, a quick helper function to draw such graphs might be more useful and efficient than importing external modules. We will explore the external modules as well but let’s first do it ourselves!

def draw_bar(value, legend=None, char="❚"):
if legend:
print(legend, "\t", char * value)
else:
print(char * value)

print("\nAWS Ping Test results: ")
print("=========================")
for d in data:
print(d["Region Code"], "\t", d["Mean"])


print("\nAWS Ping Test results: ")
print("=========================")
for d in data:
ms = int(d["Mean"].replace(" ms", ""))
ms_bar = round(ms / 10)
# print(d["Region Code"], "\t", "*" * ms_bar)

draw_bar(ms_bar, d["Region Code"])
draw_bar(ms_bar, d["Region Code"], "☐")
draw_bar(ms_bar, d["Region Code"], "░")

Here I have added a simple function to draw the bar graph and used some Unicode characters to make the graph a bit more interesting and aesthetically pleasing than our previous example

By providing your own Unicode character it can be easily changed as per your own choice or taste (mine are not very good! Proof is in the picture 😂)

Although a simple function might help in this case, however, if your script needs better visualizations there are some really good external modules let's explore these I have already used some of them in my projects.

1. Terminalplot

Terminalplot is one of the modules that are very useful for simple scatter plots. It’s very easy to use and only a few lines of code to add to your script.

from terminalplot import plot

x = range(0, 100, 2)
y = [i**2 for i in x]
plot(x, y)

This will result in the following:

The very easy-to-use modules come at the cost of not being very flexible, the plot character is not customizable and will print “*”. Also, there is no option to show labels or plot legends. So if you need a quick solution to plot any kind of mathematical expression without very minute resolution then it’s good for that purpose

2. Asciichartpy

This is a Python-ported version of the NPM module with the name asciichart. This one I have used this module in one of my projects pynetmon if you’re more interested you can read it here about how I used it in the project.

Coming back to the module although the documentation for Python is bit missing but it’s very similar to the NodeJS version so pretty easy to use let's see an example:

import asciichartpy as acp
from random import randint

x = [randint(0, 10) for _ in range(100)]

print(acp.plot(x))

This will result in the following chart:

This is very useful where you need to plot streaming data and that’s why I used it in my pynetmon project to plot the ingress and egress data on the network interface. You can also provide some configurations to customize the units or text format shown and a few more options to explore or experiment with. If you’re building a Text-based User Interface it works great with such libraries like Rich or Textual.

3. Termplot

Termplot is similar to Terminalplot mentioned above but with little more flexibility to customize different plot types.

import math
from termplot import Plot
xvals, yvals = [], []
for i in range(0, 2000, 5):
xx = i / 100.0
xvals.append(xx)
yvals.append(math.sin(xx) * float(i ** 0.5))
Plot(xvals, yvals, LINE)

This will result in the following scatter plot

Source: https://github.com/justnoise/termplot

4. Termgraph

If you need to plot a candlestick plot for any kind of financial dashboard in the terminal in that case this this module is helpful. It only does one type of plot but it’s good using Unicode character set to plot a candlestick chart is really impressive. It’s not pip installable and there’s a pip module with the same name so be careful of the ambiguity, right now you can only use it by cloning the source to your project.

Here is an example Termgraph rendering OHLC chart from CSV data on Windows Terminal:

Termgraph OHLC on Terminal!

5. Plotille

Plotile uses a really cool approach using Braille dots to print some really good resolution charts. This is one of the relatively new modules compared to the others mentioned above. I am actually considering swapping Plotile with asciicharts for pynetmon graphs.

It’s very easy to use and integrate into any script, let’s check an example:

import plotille
import psutil

temps = []
n = []
for i in range(100):
n.append(i)
temps.append(psutil.cpu_percent(interval=0.1))

fig = plotille.Figure()
print(plotille.plot(n, temps, height=30, width=60, interp="linear", lc="cyan"))

In the example I am storing the CPU usage of my system every 0.1 seconds into a list this is for simplicity in the actual application we’ll probably do it in real-time but let’s check the results for now:

As you can see the graph resolution is more precise and aesthetically better also the module is easily customizable so you can change the line color, background, etc without much hassle.

In the example I have only used a simple plot, there are also scatter or histogram plots available. Also if you need a custom graph that can be done by manipulating the Canvas. Even images can be rendered in Canvas like the following

Source: Plotile example

Pretty cool isn’t it and also enables a lot of possibilities if you’re interested in ASCII arts.

6. Termcharts

The common pattern of the libraries discussed so far is mostly limited to line, bar, and scatter plots mostly. However, if you need to plot a nice pie chart or donut chart, (yes those circular thingies from usually the business presentations on a long and boring meeting that could’ve easily conveyed in an email, but hey how’s that fun let’s invite everyone and waste 30 mins of time and achieve nothing in the end🤣sorry for the rant, but you got the gist.)

Now TLDR; Termcharts lets you print pie and donut charts in the terminal and with cool color combinations by default.

For our example let’s plot my awesome schedule throughout the day:

import termcharts
from rich import print
from rich.layout import Layout
from rich.panel import Panel

data = {"Work": 8, "Sleep": 6, "Gaming": 4, "Netflix": 4, "Misc": 2}

chart1 = termcharts.bar(data, title="Time of my life", rich=True)
chart2 = termcharts.bar(data, title="Time of my life", mode="v", rich=True) # vertical

chart_pie = termcharts.pie(data, title="Time of my life", rich=True)

chart_donut = termcharts.doughnut(data, title="Time of my life", rich=True)

layout = Layout()
layout.split_column(Layout(name="upper"), Layout(name="lower"))
layout["upper"].split_row(
Layout(name="uleft"),
Layout(name="uright"),
)
layout["lower"].split_row(
Layout(name="lleft"),
Layout(name="lright"),
)
layout["uleft"].update(Panel(chart1))
layout["uright"].update(Panel(chart2))
layout["lleft"].update(Panel(chart_pie))
layout["lright"].update(Panel(chart_donut))

print(layout)

This will result in the following (disclaimer I am nowhere near this level of productivity or scheduling 😆this is for demonstration purposes only, also the death star is not part of the charts just my terminal background.):

This module can be a nice addition to any kind of dashboard that needs this type of chart to render on the terminal if needed.

7. Plotext

Plotext is probably the most versatile of the modules we discussed in this article so far (and I saved it for the last, such a coincidence! 💡). Plotext supports most types of charts which are scatter, line, bar, histogram, datetime (time-series), candlestick some special type charts such as error plots, confusion matrices, event timelines, etc. It can show images and gifs not only that it can even play videos on the terminal but too from youtube directly!

It’s time for some examples let’s try the candlestick chart first, we have done one before with termgraph but personally I think plotext resolution is a bit better.

import plotext as plt
import yfinance as yf

plt.date_form("d/m/Y")
start = plt.string_to_datetime("01/01/2023")
end = plt.today_datetime()
data = yf.download("SPY", start, end)
dates = plt.datetimes_to_string(data.index)

plt.clf()
plt.theme("dark")
plt.candlestick(dates, data)
plt.title("SPY Stock Price CandleSticks")

plt.show()

I have changed the theme to dark mode so that fellow dark-side embracers don’t burn their eyes! The default theme is white similar to the ones we used to see with matplotlib charts. The candlestick chart looks like the following:

Plotext Candlesticks chart

For the video Demo, I will use everyone’s all-time favorite video which you will see shortly!

import plotext as plt

src = "./Rick_Astley_Never_Gonna_Give_You_Up.mp4"
plt.play_video(src, from_youtube=True)

Plotext mentions it can directly play videos from Youtube however when I tried I couldn’t play it and a lot of dependencies issues popped up so I used a local video file.

Rick Rolling on the Windows Terminal via Plotext

So now we can enjoy Rick Ashley in the Terminal as well! The from_youtube=True is needed for the audio to play if removed or set to False only the video will play without the audio.

That’s it folks I have shared 7 cool modules that you can integrate into your next terminal scripts or projects to make them look stunning!

If you enjoyed this article and want to support or encourage me feel free to follow me or subscribe to my newsletter or follow me on Twitter.

Also if you want to support my future blogging endeavor, you can buy me a coffee!

--

--

Sourav De

Python Developer & DevOps Engineer. Expertise in Python, cloud platforms, and CI/CD pipelines. Innovating at the intersection of development and operations