Skip to content

Instantly share code, notes, and snippets.

@rcarmo
Created July 3, 2026 07:19
Show Gist options
  • Select an option

  • Save rcarmo/e82804e068751586b947ae7ad075c00a to your computer and use it in GitHub Desktop.

Select an option

Save rcarmo/e82804e068751586b947ae7ad075c00a to your computer and use it in GitHub Desktop.
Stupidly Visible Temperature Display
#!/usr/bin/env python3
"""
Print the lm-sensors "Package id 0" temperature in a huge terminal font.
Usage:
./scripts/package-temp-big.py # watch, run sensors every 2s, large font
./scripts/package-temp-big.py -i 5 # watch every 5s
./scripts/package-temp-big.py --scale 3 # even larger
./scripts/package-temp-big.py --once # one-shot
sensors | ./scripts/package-temp-big.py --stdin
No external Python dependencies. Requires `sensors` from lm-sensors unless using --stdin.
"""
from __future__ import annotations
import argparse
import re
import shutil
import subprocess
import sys
import time
from typing import Iterable
# 7-line block digits. Keep glyphs monospace-friendly.
FONT = {
"0": [" █████ ", "██ ██", "██ ███", "██ █ ██", "███ ██", "██ ██", " █████ "],
"1": [" ██ ", " ███ ", " ██ ", " ██ ", " ██ ", " ██ ", "██████ "],
"2": [" █████ ", "██ ██", " ██", " ███ ", " ██ ", " ██ ", "███████"],
"3": ["██████ ", " ██", " ██", " █████ ", " ██", " ██", "██████ "],
"4": ["██ ██", "██ ██", "██ ██", "███████", " ██", " ██", " ██"],
"5": ["███████", "██ ", "██ ", "██████ ", " ██", "██ ██", " █████ "],
"6": [" █████ ", "██ ██", "██ ", "██████ ", "██ ██", "██ ██", " █████ "],
"7": ["███████", " ██", " ██ ", " ██ ", " ██ ", " ██ ", "██ "],
"8": [" █████ ", "██ ██", "██ ██", " █████ ", "██ ██", "██ ██", " █████ "],
"9": [" █████ ", "██ ██", "██ ██", " ██████", " ██", "██ ██", " █████ "],
".": [" ", " ", " ", " ", " ", " ██ ", " ██ "],
"+": [" ", " ██ ", " ██ ", "███████", " ██ ", " ██ ", " "],
"-": [" ", " ", " ", "███████", " ", " ", " "],
"°": [" ███ ", "█ █ ", "█ █ ", " ███ ", " ", " ", " "],
"C": [" █████ ", "██ ██", "██ ", "██ ", "██ ", "██ ██", " █████ "],
" ": [" "] * 7,
}
PACKAGE_RE = re.compile(
r"^\s*Package\s+id\s+0\s*:\s*\+?(-?\d+(?:\.\d+)?)\s*°?C",
re.IGNORECASE | re.MULTILINE,
)
def run_sensors() -> str:
if not shutil.which("sensors"):
raise RuntimeError("`sensors` not found. Install lm-sensors first, e.g. `sudo apt install lm-sensors`.")
proc = subprocess.run(["sensors"], text=True, capture_output=True, check=False)
if proc.returncode != 0:
raise RuntimeError(proc.stderr.strip() or "`sensors` failed")
return proc.stdout
def parse_package_temp(output: str) -> str:
match = PACKAGE_RE.search(output)
if not match:
raise RuntimeError('Could not find a "Package id 0" temperature in `sensors` output.')
value = match.group(1)
# Avoid noisy trailing .0 unless lm-sensors reports a useful decimal.
if value.endswith(".0"):
value = value[:-2]
return value
def read_package_temp(stdin: bool = False) -> str:
output = sys.stdin.read() if stdin else run_sensors()
return parse_package_temp(output)
def colour_for_temp(temp: float) -> str:
if temp >= 90:
return "\033[1;31m" # bright red
if temp >= 75:
return "\033[38;5;208m" # orange
if temp >= 60:
return "\033[1;33m" # yellow
return "\033[1;36m" # cyan
def render_big(text: str, scale: int = 2) -> str:
"""Render text with simple integer scaling.
scale=2 is intentionally huge but still fits most terminals for values like 63°C.
"""
scale = max(1, scale)
rows: list[str] = []
for glyph_row in range(7):
line = ""
for char in text:
glyph = FONT.get(char, FONT[" "])
expanded = "".join(ch * scale for ch in glyph[glyph_row])
line += expanded + (" " * (2 * scale))
for _ in range(scale):
rows.append(line.rstrip())
return "\n".join(rows)
def print_temp(clear: bool = False, stdin: bool = False, scale: int = 2) -> None:
temp_s = read_package_temp(stdin=stdin)
temp_f = float(temp_s)
label = f"{temp_s}°C"
if clear:
print("\033[2J\033[H", end="")
print(colour_for_temp(temp_f) + render_big(label, scale=scale) + "\033[0m")
print(f"Package id 0: {temp_s}°C")
def main(argv: Iterable[str] | None = None) -> int:
parser = argparse.ArgumentParser(description="Show lm-sensors Package id 0 temperature in a huge terminal font.")
parser.add_argument("--once", action="store_true", help="run sensors once and exit")
parser.add_argument("-i", "--interval", type=float, default=2.0, help="refresh interval in seconds (default: 2)")
parser.add_argument("-s", "--scale", type=int, default=2, help="font scale factor (default: 2)")
parser.add_argument("--stdin", action="store_true", help="parse sensors output from stdin instead of running sensors")
args = parser.parse_args(argv)
try:
if args.stdin and not args.once:
args.once = True
if args.stdin:
print_temp(clear=False, stdin=True, scale=args.scale)
elif args.once:
print_temp(clear=False, scale=args.scale)
else:
while True:
print_temp(clear=True, scale=args.scale)
time.sleep(args.interval)
except KeyboardInterrupt:
return 0
except RuntimeError as exc:
print(f"error: {exc}", file=sys.stderr)
return 1
return 0
if __name__ == "__main__":
raise SystemExit(main())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment