1562 words
8 minutes
Four Quick Python Projects
2026-05-29

Improving as a developer is important, but finding good ways to do it is not always obvious. At the same time, programmers have a habit of automating problems instead of just solving them. Somewhere between those two observations I found a sweet spot: small projects that solve a real, personal problem while sharpening the basics along the way.

The four projects below are nothing groundbreaking. They were never meant to be. But each of them taught me something I still use today, and writing them was more fun than doing the same task by hand would ever have been.

Travel Weather#

While packing for a multi-stop road trip, I wanted to know the weather forecast for every destination at once. Looking up city A, then city B, then city C is a five-minute job - boring, but doable. Of course, packing and clicking through forecasts back to back is no fun, so I wrote a small Python tool instead.

For the data I used OpenWeather, which has a free tier and a clean API. The tool takes a list of locations and dates and prints a compact forecast for the whole trip.

uv run python -m travel_weather --weather \
    "Salzburg:2026-04-28:+1" \
    "Bridgetown:2026-04-29" \
    "Kiruna:2026-04-29:+1"

would print something like

Weather forecast for city: Salzburg
Start date: 2026-04-28
End date: 2026-04-29
2026-04-28: min 12.1°C, max 17.0°C, mostly ☁️ clouds
  12:00   16.9°C ☀️ clear sky
  15:00   17.0°C ☁️ scattered clouds
  18:00   13.7°C 🌦️ light rain
  21:00   12.1°C ☁️ overcast clouds
2026-04-29: min 4.4°C, max 14.2°C, mostly ☁️ clouds
  00:00    8.5°C 🌦️ light rain
  03:00    8.6°C 🌦️ light rain
  06:00    6.7°C 🌦️ light rain
  09:00    7.7°C ☁️ overcast clouds
  12:00   13.2°C ☁️ overcast clouds
  15:00   14.2°C ☁️ scattered clouds
  18:00    8.0°C ⛅️ few clouds
  21:00    4.4°C 🌙 clear sky
Summary for Salzburg: Min Temp: 4.4°C, Max Temp: 17.0°C Layer up - it's a grey one. Bundle up with a 🧣, 🧤 and a warm jacket.
-----------------------------------------------------------------------------------------------------------------------------

Weather forecast for city: Bridgetown
Start date: 2026-04-29
End date: 2026-04-29
2026-04-29: min 26.0°C, max 27.9°C, mostly ☁️ clouds
  00:00   26.5°C ☁️ scattered clouds
  03:00   26.3°C ☁️ broken clouds
  06:00   26.0°C ☁️ broken clouds
  09:00   26.0°C ☁️ overcast clouds
  12:00   26.9°C ☁️ broken clouds
  15:00   27.9°C ☀️ clear sky
  18:00   27.9°C ⛅️ few clouds
  21:00   27.3°C ☁️ overcast clouds
Summary for Bridgetown: Min Temp: 26.0°C, Max Temp: 27.9°C Layer up - it's a grey one. Pick lightweight, breathable layers.
---------------------------------------------------------------------------------------------------------------------------

Weather forecast for city: Kiruna
Start date: 2026-04-29
End date: 2026-04-30
2026-04-29: min -5.6°C, max -0.2°C, mostly ☁️ clouds
  00:00   -5.6°C ☁️ broken clouds
  03:00   -5.2°C ☁️ overcast clouds
  06:00   -3.4°C ☁️ overcast clouds
  09:00   -2.9°C ❄️ light snow
  12:00   -1.7°C ❄️ light snow
  15:00   -0.2°C ☁️ overcast clouds
  18:00   -0.5°C ☁️ overcast clouds
  21:00   -0.9°C ☁️ overcast clouds
2026-04-30: min -0.7°C, max 4.5°C, mostly ☁️ clouds
  00:00   -0.3°C ☁️ broken clouds
  03:00   -0.7°C ☁️ overcast clouds
  06:00    1.5°C ☁️ overcast clouds
  09:00    4.1°C ☁️ overcast clouds
  12:00    4.5°C ☁️ overcast clouds
  15:00    3.0°C ☁️ overcast clouds
  18:00    3.4°C ☁️ overcast clouds
  21:00    2.3°C ☁️ overcast clouds
Summary for Kiruna: Min Temp: -5.6°C, Max Temp: 4.5°C A layered outfit suits today's clouds. Pull out the warm jacket, 🧣 and 🧤.
--------------------------------------------------------------------------------------------------------------------------------

Summary for all cities:
Warmest City (Bridgetown): Dress in layers. Pick lightweight, breathable layers.
Driest City (Bridgetown): Dress in layers. Lightweight and breathable - you'll thank yourself.
Coldest City (Kiruna): Stick to layered clothing today. Bundle up with a 🧣, 🧤 and a warm jacket.
Wettest City (Salzburg): Dress in layers. Layers help - the temperature will swing.
--------------------------------------------------

What stuck with me from this one was working with HTTP APIs from Python for the first time.

This was actually one of the first projects I used AI with. I thought it was a nice idea to add text for the clothing and of course AI added emojis.

Finding cheap flights gets harder the more flexible you are. I often knew roughly when I wanted to travel but had several possible origin airports, no fixed destination and a flexible return date. Web-based flight search engines hit their limits quickly under that kind of input.

So I solved it the same way I solved Travel Weather: a Python tool, this time on top of the Kiwi Tequila API. It takes a list of origin airports, a list of destinations, an acceptable travel window, a stopover limit and returns the cheapest combinations it can find.

It also taught me to think about API budgets. Two origins, two destinations, two start dates and two end dates already produce 16 calls. Adding a third destination jumps it to 24. That number grows fast - the relationship is plain enough:

def count_api_calls(
    origins: list[str],
    destinations: list[str],
    start_dates: list[str],
    return_dates: list[str],
) -> int:
    return len(origins) * len(destinations) * len(start_dates) * len(return_dates)

One multiplication, four inputs - and each added option multiplies the cost rather than adding to it. That alone shaped every later flag: anything that lets the user narrow the search space earns its place.

I also tried to make the tool more approachable by wrapping it in a small web UI using PyWebIO. Building a CLI that is both powerful and friendly is genuinely hard, and that experiment was a useful reminder of why most “quick” tools stay command-line only.

The real lesson here was about constraints. Without them, the cheapest flight is usually a 30-hour itinerary with three layovers - technically the answer to “find the cheapest flights”, but not what I actually wanted. That is why the CLI options grew over time, with the stopover limit being the obvious example. I never used the tool as much as I had hoped, mainly because my travel volume dropped not long after - but designing around real-world constraints, rather than just the API’s, has stayed with me.

TickTick to Joplin#

For years I have been using TickTick as my todo app. While looking into self-hosting more of my own tooling, I found Joplin, which doubles as a note-taking app and stores everything as plain Markdown. The same instinct that led me to replace my old Image to Text tool with Paperless-ngx was at play here: I liked the idea of owning my data in a portable format.

Joplin happily imports folders of generic Markdown but not TickTick’s specific export format, so I wrote a small Python converter to bridge the two.

Most of the work was not the wiring between formats. It was the small ambushes hiding in the data. All-day reminders, for example, were exported as UTC midnight. After converting to Vienna time that lands in the small hours of the night, and a reminder firing then helps no one - so all-day items had to be pinned to a sensible hour instead:

from datetime import time
from zoneinfo import ZoneInfo

local = utc_dt.astimezone(ZoneInfo("Europe/Vienna"))

if local.time() == time(0):
    local = local.replace(hour=9)

Every TickTick row had a small surprise like this - the kind of detail that never shows up in an export spec but breaks immediately the moment a user tries to live with the result.

The converter did its job, and the project taught me a lot about taking messy exported data, reshaping it and handing it to another tool in the form it expects. The migration itself, on the other hand, never really happened. I never set a hard cut-off date after which new tasks had to land in Joplin instead of TickTick, and without that deadline, the old habit won.

Person Event Statistics#

At some point I got curious about how the length of an ongoing phase of life compares to the rest of it. How much of my life have I spent studying? What share of it has been with my current employer? It is the kind of question you can answer on the back of an envelope, but I had recently been enjoying Python and decided to write something for it.

As usual, I went a little overboard - and had fun doing it. The tool reads events from a JSON file and visualizes them. It started out printing plain statistics, until I discovered Python’s built-in tkinter and added a small GUI on top. With that in place, adding new events from the UI and rendering them as a bar chart against total lifetime came naturally.

It is in the same spirit as my early Weatherstation and Image to Text projects: pick a small itch, scratch it in Python and let the side quests teach you something new.

Looking back, this one was built during a demanding stretch in my personal life, where a lot of things were out of my hands. Having a small, self-contained coding task with clear inputs and a clean endpoint turned out to be unexpectedly grounding. A quiet reminder that side projects can serve more than just curiosity.

Final thoughts#

These projects are a small sample of things I have built that never made it anywhere public. None of them solved a problem I could not have solved by hand. All of them were more interesting because I solved them with code.

The pattern is almost always the same. I get a working prototype, then I keep adding features for fun, and somewhere in that second phase I end up learning the actual lesson:

  • How to design a CLI that is comfortable to use.
  • Staying focused on the original problem instead of disappearing into the tooling around it.

In the end, learning new things while solving an existing problem is what keeps me coming back. There is always another small itch worth scratching.

Enjoyed the post? Have questions or feedback? I'd love to hear from you! Feel free to drop me an email at blog@jerey.at.

Four Quick Python Projects
https://jerey.at/posts/quick-python-projects/
Author
Anton A. Jerey
Published at
2026-05-29
License
CC BY-NC-SA 4.0