S

HomeBlogs

I Gave Python a Shot (And Here's What I Learned)

Six or seven years ago, Python and I had a very short, very polite relationship. Class 11. Basics. Exams. Goodbye. Then life happened. JavaScript happened. Startups happened. Until last month, when I picked it up again for an ETL project. Here's what I learned.

Published on January 20, 2025

I Gave Python a Shot (And Here's What I Learned)

The Short Relationship

Six or seven years ago, Python and I had a very short, very polite relationship.

Class 11. Basics. Exams. Goodbye.

Then life happened. JavaScript happened. Startups happened. APIs, infra, deadlines, production fires. Python stayed untouched — not rejected, just… irrelevant.

Until last month.

Picking It Up Again

I was building an ETL project. Real data. Ugly CSVs. Files that looked like they were generated by chaos itself. I needed dataframes, analytics, something that wouldn't fight me while I was trying to move data from A to B and maybe make some money along the way.

So I picked up Python again.

Not casually. Properly.

Refreshing the Basics

I spent the first week just refreshing basics — arithmetic, conditionals, functions, classes, dunder methods, packages, modules. Stuff I technically “knew” but had never truly used back when it was exam material. This time, it landed differently.

Classes stopped feeling academic. Dunder methods stopped feeling like spells. They felt like agreements. Clear, intentional behavior. Python wasn't being magical — it was being honest.

Even revisiting basics like dunder methods felt different this time.

class Job:
    def __init__(self, name: str):
        self.name = name

    def __str__(self):
        return f"Job({self.name})"

Not magic. Just clearly defined behavior.

Indentation: The Surprise

I went in fully prepared to hate indentation. No curly braces felt illegal at first. Years of muscle memory screaming for {}. But weirdly… it didn't bother me.

After a few days, indentation stopped being something I noticed and started being something that helped. The code looked exactly how it ran. No hidden scope. No surprises. If it was ugly, it looked ugly. Fair enough.

Named Arguments: Delight

Then there were named arguments.

This one genuinely delighted me.

Calling a function and saying exactly what I meant — without wrapping everything into an object just to keep my sanity — felt like relief. The intent sat right there at the call site. No guessing. No scrolling. No mental tax. Clarity, by default.

def process_data(limit: int, retry: bool, timeout: int):
    ...

process_data(limit=100, retry=True, timeout=5)

No object wrapping gymnastics. No guessing argument order. The call site tells the truth about what's happening.

Standard Library: Quiet Flex

And the standard library?

That was a quiet flex.

Math, dates, time, decimals, statistics — things I usually patch together in JavaScript with libraries and prayers — were just… there. Python felt like a language that had seen real-world problems and decided to help instead of staying minimal for philosophical reasons.

Dataframes: Thinking in Tables

That's when dataframes entered the picture.

Pandas made me stop thinking in loops and start thinking in tables. Polars felt sharp and opinionated. DuckDB felt straight-up illegal — analytical SQL, locally, directly on files, without spinning up infra or begging for permissions. Suddenly, ETL didn't feel like plumbing. It felt like asking good questions and getting fast answers.

Working with DuckDB felt borderline unfair.

import duckdb

con = duckdb.connect()

df = con.execute("""
    SELECT country, COUNT(*) as users
    FROM 'users.csv'
    GROUP BY country
""").df()

No server. No setup. Just SQL on a file, locally, fast enough to make you suspicious.

And with Polars, dataframes finally felt sharp instead of bloated.

import polars as pl

df = pl.read_csv("events.csv")

result = (
    df
    .filter(pl.col("status") == "success")
    .group_by("type")
    .count()
)

No loops. No mutation soup. Just transformations that read like intent.

Understanding JavaScript Better

Somewhere in this process, something unexpected happened.

Python made me understand JavaScript better.

Coming back to a synchronous, predictable execution model made the JS event loop finally click. The call stack stopped being abstract. Async stopped feeling random. The contrast clarified everything. Python gave me calm. JavaScript showed me chaos — but intentional chaos. I stopped blaming myself for async bugs and started respecting the environment JS operates in.

Tooling: From Chaos to Order

Then came tooling.

At first, pip scared me. Global installs everywhere. One project breaking another. Pure anxiety. Then I found venv, and order was restored. Isolated environments. Clear boundaries. Sanity.

And then… uv.

As a JS dev raised on npm and lock files, this felt like home. Fast installs. Deterministic behavior. Reproducibility without rituals. It removed a kind of background stress I didn't even realise I was carrying.

Environment sanity check — venv + uv, the combo that saved my mental health.

python -m venv .venv
source .venv/bin/activate

uv pip install fastapi polars duckdb

Locked. Isolated. Reproducible. As a JS dev, this finally felt… civilized.

FastAPI: The Smile Moment

FastAPI was the moment I genuinely smiled.

This was literally my FastAPI hello world. No generator. No scaffolding sermon.

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def hello():
    return {"message": "hello"}

That's it. No hidden magic. No “you'll understand this later.” You read it once and your brain says: okay, I get it.

Then came Pydantic, where my inner TypeScript dev finally relaxed.

from pydantic import BaseModel

class User(BaseModel):
    id: int
    email: str
    is_active: bool = True

Pass bad data into this and it doesn't “kinda work.” It fails. Immediately. Loudly. At the boundary.

That's not strictness — that's respect for production.

No drama. No ceremony. No “enterprise-ready” lecture before hello world. Just trust. And quietly — validation, typing, OpenAPI docs, async support — all there when needed. It felt designed by people who had shipped under pressure and remembered what friction costs.

SQLAlchemy: Trust Broke

And then… SQLAlchemy.

That trust broke a little.

Powerful? Absolutely.

Developer-friendly? Not immediately.

It felt like it wanted me to understand databases as a concept before letting me save a row. Sessions, engines, mappers — a lot of abstraction before momentum. Not bad. Just heavy. Especially after tools that had been working so hard to stay out of my way.

The Pattern: Friction Reduction

At that point, the pattern was obvious.

The tools I enjoyed most weren't the fanciest.

They were the ones that reduced friction.

Polars. DuckDB. Pydantic. FastAPI. uv.

They didn't try to impress me. They tried to unblock me.

None of this code is impressive on its own.

That's the point.

It's boring in the best way — the “this will work at 2 a.m.” way.

Python didn't make me feel smarter. It made me feel calmer.

And when your tools stop fighting you, you stop wasting time proving things — and start shipping things that earn their keep.

Zed Editor and DSAs

I even gave Zed editor an honest shot — no AI, no copilots. Just me and the code. It felt uncomfortable at first. Then strangely calming. I started thinking more before typing. Writing less junk. Being more deliberate.

Zed Editor showing FastAPI application

Alongside all this, I started revisiting DSAs. Not for interviews. Not for flexing. Just to sharpen instincts. To understand why things are fast, slow, expensive, or elegant. Quiet confidence, not loud preparation.

Clarification, Not Replacement

This whole Python journey didn't replace JavaScript for me.

It clarified it.

It didn't make me obsessed with theory.

It made me obsessed with outcomes.

Python didn't make me feel clever.

It made me feel effective.

And that's the biggest compliment I can give a tool.

I'm still learning. Still breaking things. Still discovering sharp edges. But this has been one of the most satisfying learning curves I've had in a while — not because it's trendy, but because it's practical.

I'll keep sharing updates as I go.

And if any of this resonated — if you're juggling stacks, questioning tools, or just trying to ship without losing your sanity — reach out to me over email.

Because at the end of the day, software has only one real job:

To work.

And to earn its keep.