> the Python interpreter is natively integrated in all Unix distros
It's included in the default install of most desktop/server Linux distros (with plenty of exceptions), but I don't believe any of the BSDs ship it in their base system.
IIRC macOS used to have python 2 in its default install, but I vaguely recall that being deprecated and removed at some point. My only Mac is on the other side of the country at the moment, so I can't check myself.
> Python has done a good job of hiding its legacy ugliness (such as __init__, __new__, and similar aberrations), swettening its syntax to accomodate developers with good taste.
What exactly is the problem with __init__ or __new__? @dataclass is very nice syntactic sugar, but are we arguing here that having access to initializer/allocator/constructor dunder methods is "legacy ugliness"? This is the core of pythonic built-in aware python. Bizarre.
I've been doing Python professionally for a while (~10-ish years in backend web dev and file processing), and while I don't like how exactly the author described dunder methods as "legacy", it's still not a language facility I reach out to often because, well, it's sort of odd coming from a C# background. The author has blog posts about Java, which isn't that different from C#, so maybe that's the reason.
Maybe as I grow to think of the "big picture" architecture-wise with my code, I will start incorporating dunders, but until then...
It's like the (usually) interpreted equivalent to C/C++. There are lots of 'standard' package management choices.
And it seems like the package resolution is finally local by default, although that requires a 'virtualenv', which seems to be a legacy of the global packaging system.
I expect that for every two python users who know what `pip` is, there are three who are discouraged from thinking about the environment at all. Given that, focusing on the language and not the packaging is the right choice. Packaging is most often somebody else's problem.
It's just HN users are more likely to be that somebody else. Probably we have to deal with non-python dependencies anyway so we're reaching for bigger hammers like docker or nix. It would be nice if there wasn't a mess of python package managers, but whichever one I use ends up being a somewhat unimportant middle-layer anyway.
It's funny, I'm the opposite: LLMs have made it easy to draft something in Python, then translate to a more appropriate language for the target problem-domain, for example Go.
Agree . We had training to learn how LLM applications can be developed and it was obviously in Python. Never liked Python but between dependencies issues (the demo project used uv but somehow the author forgot to declare some dependencies which she probably had installed globally) which cost hours of everyone’s time, and the persistent magic going on (pipe operators that do nothing similar to unix pipes, wtf!, puydantic shit just to declare a data type with metadata and lots of things like this) nearly everyone immediately switched to a typed language like Kotlin (they have a nice AI framework) as soon as we got the basics of how things work.
Is go the language that doesn't include a module to do mmap and doesn't include a module to place binary data into a struct?
If you want to read binary files, you can use C or python, but not go (unless you use segfault prone 3rd party libraries of very dubious quality, of course).
If you are working in Data Science/ML its the best bet for handling dependencies in your project compared to the rest of the tools. Its use has exploded, especially because you can do ‘uv pip whatever’ if you insist on using pip.
There's only one kind of Python virtual environment, and both uv and the standard library `venv` module make them (as does third-party support like `virtualenv`). The differences are in what gets put in them (aside from the actual packages you explicitly install), and in the interface for configuring that. In particular, the standard library defaults to bootstrapping pip, but you can easily skip that. And of course uv does not bootstrap pip, because it does pip's job (and much more).
I like Python for the language, and for a lot of jobs the threading model limitations do not matter. Its a great language to get stuff done. I find the package management story challenging but I will try uv next time!
From what? It would be useful to mention towards the front of the post so we know what is the context in which you approach python.
I've switched to python primarily (from perl) in early 2010s (I think my first "seriously" used version was 2.6. This is mostly for system management, monitoring, and data transformation /visualisation. Nothing fancy like AI back then in a work setting.
I found the biggest impact was not so much on writing code but on it remaining readable for a very long time, even if it was created hastily "just get this working now" style. Especially in a team.
Python is still one of my favourites and the first tool I reach if bash is not enough for what I'm trying to do.
From what I was told, Python was originally seen as a Swiss Army knife for sysadmins. It started gaining more traction when Canonical adopted it as the main language for Ubuntu 4.10 in 2004.
Then, in 2005, Guido van Rossum was hired by Google to work on Google Cloud. That opened the door for wider adoption in academia, since Python had strong math libraries and integrated well with tools researchers were already using, like Hadoop, right around the time big data and ML were starting to take off.
Also, between 2005 and 2006, two important things happened: Ruby on Rails came out and inspired Django, which was starting to gain popularity, and web developers were getting tired of Perl's messy syntax. That's how Python quickly became a solid choice not just for server-side scripts, but for building proper web apps. In the meantime, another language that could be embedded directly into HTML was storming the web: PHP. Its syntax was similar to JavaScript, it was easy to pick up, lowered the barrier to entry for software development, worked straight out of the box, and didn't require thousands of print statements to get things done.
The 3 Ps made history. According to programmers from 20 years ago, they were like religions. Each had its own philosophy and a loyal group of followers crusading online, getting into heated debates, all trying to win over more adopters. The new generation of devs is more pragmatic. These days it's less about language wars and more about picking the right tool for the job.
The key factor imo was Travis Oliphant merging the competing numeric and numarray libraries into numpy in 2005. That quickly became the foundation of Python as the key environment for open source numeric processing.
It brought across a ton of users from R and Matlab.
Pandas, Matplotlib and ScikitLearn then consolidated Python's place as the platform of choice for both academic and commercial ML.
> According to programmers from 20 years ago, they were like religions. Each had its own philosophy and a loyal group of followers crusading online, getting into heated debates, all trying to win over more adopters.
It's very weird reading something you lived through described in these terms, as though it were being described by an anthropologist.
Can't help but wonder what the future will have to say about today.
"In 2025, programmers used 'frameworks' to hang 'apps' from some kind of 'web'. They believed these frameworks gave them magic powers. Many even fought in 'flame wars' on this topic, which experts believe involved the use of fire to destroy webs woven by competing programmers."
> The 3 Ps made history. According to programmers from 20 years ago, they were like religions. Each had its own philosophy and a loyal group of followers crusading online, getting into heated debates, all trying to win over more adopters. The new generation of devs is more pragmatic. These days it's less about language wars and more about picking the right tool for the job.
I feel like the religious wars aspects of this is completely overblown. The conversations around languages really hasn't changed all that much in the last 20 years. Look at the way you see things happening in HN, heck even in the comment thread right here. It's the exact same kinds of discussions as happened back 20 years ago, with exactly the same kind of pragmatism.
I think the gulf comes about from the fact that the primary sources are conversations occurring between people that are largely anonymous behind an online handle, interacting with people that aren't face to face. There's always been an element of exaggeration in the interactions. What might be a "Umm, no" with a maybe a shake of the head, becomes "Your mother was a hamster and your father smells of elderberries". Almost every party involved comes to recognise the particular cultural quirks (which varied from forum to forum) and how to translate what was said, to what was actually meant.
>From what I was told, Python was originally seen as a Swiss Army knife for sysadmins.
Yea, I was a sysadmin around 2000 (before that too) and I knew it as such.
>between 2005 and 2006, two important things happened:
Somewhat - I used it in 2001 for Plone which is based on Zope, which was somewhat popular around that time. Writing all the web stuff with Python made sense, since Plone provided a CMS and could include a wiki. Adding on some sql calls to it in python just made sense. The competition was between PHP and Python, though there were some other less popular choices. Ruby on Rails definitely was getting a lot more popular around those times. PHP didn't start getting popular around 2005, if anything, people started using Python more, and started criticizing the crappy code that was circulating in the PHP community.
In any case, it was a fun time, but what's the point of looking back like that?
This aligns with what I remember and Guido going to Google explains things. Mid 2000's was all about PHP (Cake/Symphony/CodeIgniter/etc) vs Ruby (Rails) in the open source world. I remember hearing about Python only in sysadmin work and Plone. Then, suddenly were suddenly a lot of articles from Google about just about everything, all in Python.
I remember saying to a coworker, "Google is single-handedly keeping Python alive."
Then bam. It was everywhere. Mid 2010's, I took a cybersec job and they told me to learn Python in the two weeks between accepting and starting. "Python is all over cybersec," I was told. It was then I realized Python took over academia, which positioned it perfectly for ML. It's features made it easy to start, but it also benefited from right place, right time.
I'd say the switch was learning that Google Search was written in Python (remember when error pages URL were in .py ?), and Youtube rewritten in Python. After that, reddit and dropbox followed (and later Instagram).
Apple also added Python in, I think, Mac OS X Jaguar, so it blipped on the radar.
When you have big players using it, the community automatically grows.
Django was the continuity of that and definitely contributed to the growing popularity of Python, but I think the hype started way before (and in fact we had to suffer Zope/Plone/Twisted for it :)).
Another decisive date was circa 2010 when the Belgian book "learn programming with python" came out. Granted, Django was already 5 years old at the time, but it brought many beginners who knew nothing about programming at the time.
I'm glad someone else discovered they can like python.
I got forced to learn it for a project where I was proposing Ruby and the customer insisted on Python. This was years ago when Ruby was much slower. I was annoyed but I got used to it and here I am enjoying it many years later.
I take issue with the description and use of make though! :-D What is the point of it if you're not going to use dependencies? One might as well just write a script with a case statement..... I'm adding smileys because I don't mean to be all that serious but I really do think that the failure of the youth of today to get to grips with Make is a sad reflection on our culture....... and get off my lawn, ok? :-)
> One might as well just write a script with a case statement.....
I started with this and evolved into simple flat Makefiles, because they're basically the same but Make feels more standard (there's a Makefile here vs. there's a random bash script here).
Python has done an impressive job over the years of making steady robust improvements. The typing and tooling has just gotten better and better. There are still plenty of problems though, imho async is still a much bigger pain than it should be (compared to other runtimes with a very nice experience like go or elixir, even dotnet has been less pain in my experience). Overall I like python, but it mainly boils down to the robust libraries for things I do (ML, Data munching/analysis)
It's quite crazy, as Python first version was in 1991, 4 years before Java. It's a language with a ton of legacy baggage, the 2/3 transition, the BDLF being replaced by a completely different project leadership system, and it still keeps going strong.
This interview from Brett Cannon (old core dev who worked on packaging, imports, the vscode python extension...) is eye opening:
The guy cares SO MUCH and they have so many things not to break you can feel the sense of passion and the weight of responsibility in everything he says.
> I started to code more in Python around 6 months ago. Why? Because of AI, obviously. It’s clear (to me) that big money opportunities are all over AI these days.
I find this depressing. Not only are LLMs covertly reducing our ability to think and make decisions, they’re now also making people voluntarily conform to some lower common denominator.
It’s like humanity decided to stagnate at this one point in time (and what a bad choice of point it was) and stop exploring other directions. Only what the LLM vomits is valid.
Unpopular opinion: I think I’m going to wait for version 4 /jk. But honestly, I’ve been spoiled by modern languages like Rust, Go, and even TypeScript with modern tooling, strong typing, stability, and performance out of the box. Right now, I’m just interacting with LLMs, not building them.
That said, I remember writing myself a note a few years ago to avoid Python projects. I had to clean up code from all over the company and make it ready for production. Everyone had their own Python version, dependencies missing from requirements.txt, three way conflicts between 2 dependencies and the python version, wildly different styles, and a habit of pulling in as many libraries as possible [1]. Even recalling those memories makes my stomach turn.
I believe constraints make a project shine and be maintainable. I'd prefer if you throw at me a real python instead of a python project.
[1] Yes, I'm aware of containers, I was the unlucky guy writing them.
> Not only because the syntax is more human-friendly, but also because the Python interpreter is natively integrated in all Unix distros
That's kind of very optimistic evaluation - literally anything beyond "import json" will likely lead you into the abyss of virtual envs. Running something created with say Python 3.13.x on Ubuntu 22.04 or even 24.04 (LTSs) / Rocky 9 and the whole can of worms opened.
things like virtual envs + containers (docker like)/version managers become a must quickly.
I have a silly theory that I only half joke about that docker/containers wouldn't've ever taken off as fast as it did if it didn't solve the horrible python dependency hell so well. You know something is bad when fancy chrooting is the only ergonomic way of shipping something that works.
My first taste of Python was as a sysadmin, back in 2012 or so, installing a service written in Python on a server. The dependency hell, the stupid venv commands, all this absolute pain just to get a goddamn webserver running, good lord. It turned me off of Python for over a decade. Almost any time I saw it I just turned and walked away, not interested, no thanks. The times I didn't, I walked right back into that pile of bullshit and remembered why I normally avoided it. The way `brew` handles it on macOS is also immensely frustrating, breaking basic pip install commands, installing libraries as commands but in ways that make them not available to other python scripts, what a goddamn disaster.
And no, I really have no clue what I'm talking about, because as someone starting out this has been so utterly stupid and bewildering that I just move on to more productive, pleasant work with a mental note of "maybe when Python gets their shit together I'll revisit it".
However, uv has, at least for my beginner and cynical eyes, swept away most of the bullshit for me. At least superficially, in the little toy projects I am starting to do in Python (precisely because its such a nicer experience), it sweeps away most of the horrid bullshit. `uv init`, `uv add`, `uv run`. And it just works*.
Yes, please use virtual envs or containers. I know it seems overly heavy and hard to manage, but you don't want to end up in a situation where you're afraid to update the system because the library upgrades might break some of your Python code.
3. run ./configure --enable-optimizations --with-lto
4. run make -s -j [num cores]
5. sudo make altinstall
This will install that specific version without overwriting default system python.
You can then bash alias pip to python3.xx -m pip to make sure it runs the correct one.
All the libraries and any pip install executable will be installed locally to ~/.local folder under the specific python version.
Alternatively, if you work with other tools like node and want to manage different versions, you can use asdf, as it gives you per folder version selection.
virtual environments are really only useful for production code, where you want to test with specific versions and lock those down.
I agree that the built-in Python is typically not suitable for development, especially if you're planning to distribute your code and/or care about the versions of its dependencies. (And especially on Debian and its derivatives, in my experience; they even remove parts of the standard library, like Tkinter [0].)
I disagree that virtual environments represent an "abyss". It takes very little effort to learn how they work [1], plus there a variety of tools that will wrap the process in various opinionated ways [2]. The environment itself is a very simple concept and requires very few moving parts; the default implementation includes some conveniences that are simply not necessary.
In particular, you don't actually need to "activate" a virtual environment; in 99% of cases you can just run Python by specifying the path to the environment's Python explicitly, and in the exceptional cases where the code is depending on environment variables being set (e.g. because it does something like `subprocess.call(['python', 'foo.py'])` to run more code in a new process, instead of checking `sys.executable` like it's supposed to, or because it explicitly checks `VIRTUAL_ENV` because it has a reason to care about activation) then you can set those environment variables yourself.
Creating a virtual environment is actually very fast. The built-in `venv` standard library module actually does it faster in my testing than the equivalent `uv` command. The slow part is bootstrapping Pip from its own wheel - but you don't need to do this [2]. You just have to tell `venv` not to, using `--without-pip`, and then you can use a separate Pip (for recent versions — almost the last 3 years now) copy cross-environment using `--python` (it's a hack, but it works if you don't have to maintain EOL versions of anything). If you need heavy-duty support, there's also the third-party `virtualenv` [3].
Much of the same tooling that manages virtual environments for you — in particular, pipx and uv, and in the hopefully near future, PAPER [4] — also does one-off script runs in a temporary virtual environment, installing dependencies described in the script itself following a new ecosystem standard [5]. Uv's caching system (and of course I am following suit) makes it very fast to re-create virtual environments with common dependencies: it has caches of unpacked wheel contents, so almost all of the work is just hard-linking file trees into the new environment.
+1 - I've been shocked at how many little portability issues that I've had shipping software, even within the relatively constrained environment of fellow employees.
Minor differences between distro versions can make a big difference, and not everyone that uses a Python script knows how to use something like pyenv to manage different versions.
Good write up, and solid choices. As someone primarily working in python in the last few years, I have a very similar stack.
Two additional suggestions:
* mise to manage system dependencies, including uv version and python itself
* just instead of make; makefile syntax is just too annoying.
Mise actually has a command runner as well which I haven't tried yet, and might work better for running commands in the context of the current environment. It's pretty nice when your GitHub actions workflow is just:
I've avoided Python for a long time, but I'm getting roped in myself, mainly because certain tasks seem to require a lot less code than Java or Perl.
That said, call me old-fashioned, but I really take issue with "curl $URL | bash" as an installation method. If you're going to use an install script, inspect it first.
If your going to execute the code anyway, you either have to inspect everything or trust whoever is providing it. There is nothing special about bash that makes it more dangerous to execute than python.
Just a small note on the code in the linked script:
API_KEY = os.environ.get("YOUTUBE_API_KEY")
CHANNEL_ID = os.environ.get("YOUTUBE_CHANNEL_ID")
if not API_KEY or not CHANNEL_ID:
print("Missing YOUTUBE_API_KEY or YOUTUBE_CHANNEL_ID.")
exit(1)
Presenting the user with "Missing X OR Y" when there's no reason that OR has to be there massively frustrates the user for the near zero benefit of having one fewer if statement.
if not API_KEY:
print("Missing YOUTUBE_API_KEY.")
exit(1)
if not CHANNEL_ID:
print("Missing YOUTUBE_CHANNEL_ID.")
exit(1)
Way better user experience, 0.00001% slower dev time.
I feel like use case and audience matters when making these decisions. In this case, the user is probably someone interacting with a python script they're running in a console (I assume by print), then I really don't think it matters - the user will check that both things are set. Should you also give them some documentation about setting env vars? Should you customize that documentation to the OS they're running? etc.
If the user is a typical consumer using a typical consumer interface, then yes you want to handhold them a bit more.
Neophytes take notice. Attention to details like this is what separates truly great programmers from merely good ones. That said, for scripts reusable by others you should use command line arguments . Environment variables in lieu of command line arguments is a huge code smell.
Typer has a great feature that lets you optionally accept argument and flag values from environment variables by providing the environment variable name:
if not API_KEY and not CHANNEL_ID:
print("Missing both YOUTUBE_API_KEY and YOUTUBE_CHANNEL_ID.")
exit(1)
if not API_KEY:
print("Missing YOUTUBE_API_KEY.")
exit(1)
if not CHANNEL_ID:
print("Missing YOUTUBE_CHANNEL_ID.")
exit(1)
That way you don't end up fixing one just come back and be told you're also missing another requirement
Thank you. I see something like this all the time on one of the sites I use for work. If you fail the 2-factor, it'll tell you your password was wrong and reset the whole thing instead of telling you the 2-factor code was wrong or expired.
“I started to code more in Python around 6 months ago. Why? Because of AI, obviously. It’s clear (to me) that big money opportunities are all over AI these days. And guess what’s the de facto programming language for AI? Yep, that sneaky one.”
"And guess what's the de facto programming language for AI? Yep, that sneaky one."
Is this referring at all to to PyTorch. If not, any guesses what the author has in mind
"Not only because the syntax is more human-friendly, but also because the Python interpreter is natively integrated in all Unix distros."
Is this referring to GNU/Linux.
UNIX (UNIX-like) includes more than Linux; some UNIX distributions do not include Python in the base system
Where it is left as choice to the user whether to install it
I know this because I use such distributions and, unless some software needs it, I do not install Python
In such case, when I am done using that software I uninstall it^1
For example, he mentions retrieving YouTube channel metadata
I do not use Python for this; I use a 19-line shell script (ash not bash), its startup time is faster
Unlike Python, it is included in the base system of the UNIX distributions (both Linux and BSD) that I use
But if I need to test something using yt-dlp, then I might temporarily install Python
1. I compile Python from source and one annoying aspect of the project , in addition to the slow startup time, is their failure to include an uninstall target in their Makefile
For this script I have "implemented HTTP" using printf, an ash builtin.
The TCP networking is done with orginal netcat reading the HTTP from a pipe.
The TLS is handled by a TLS forward proxy listening on the loopback.
The orginal netcat and other TCP clients I use, like tcpclient from djb's ucspi or tcploop from haproxy, are not part of the NetBSD base system but are easily added when I compile the OS. For Linux I use a custom distribution I make myself, without LFS. Busybox has ash and nc together in the same binary.
These TCP client programs are stationary targets, they will work reliably year after year, and small enough that I can store and compile them quickly even on computers with modest resources. Python is constantly evolving, a moving target, and much larger.
I wrote a utility in C89 that "implements HTTP" called yy025. This is produced using GCC, specifically flex, which is intsalled on all systems I use. flex is part of the NetBSD toolchain. It's a requirement for compiling the OS. It's a requirement for building many GNU userland utilities. It's even a listed requirement when building the Linux kernel.
yy025 is what I normally use in shell scripts when I need to generate HTTP. It reads URLs on stdin and outputs customised HTTP to stdout. There is no "third party dependency" for HTTP. This is a "first party" program. I wrote it.
But this script to fetch YouTube metadata doesn't use yy025. It's just some printf statements.
116 comments
[ 4.7 ms ] story [ 101 ms ] threadIt's included in the default install of most desktop/server Linux distros (with plenty of exceptions), but I don't believe any of the BSDs ship it in their base system.
IIRC macOS used to have python 2 in its default install, but I vaguely recall that being deprecated and removed at some point. My only Mac is on the other side of the country at the moment, so I can't check myself.
What exactly is the problem with __init__ or __new__? @dataclass is very nice syntactic sugar, but are we arguing here that having access to initializer/allocator/constructor dunder methods is "legacy ugliness"? This is the core of pythonic built-in aware python. Bizarre.
Maybe as I grow to think of the "big picture" architecture-wise with my code, I will start incorporating dunders, but until then...
And it seems like the package resolution is finally local by default, although that requires a 'virtualenv', which seems to be a legacy of the global packaging system.
It's just HN users are more likely to be that somebody else. Probably we have to deal with non-python dependencies anyway so we're reaching for bigger hammers like docker or nix. It would be nice if there wasn't a mess of python package managers, but whichever one I use ends up being a somewhat unimportant middle-layer anyway.
If you want to read binary files, you can use C or python, but not go (unless you use segfault prone 3rd party libraries of very dubious quality, of course).
Made me think this is probably normally a Ruby developer indoctrinated against Python. The article doesn’t seem to say what they have come from.
I've switched to python primarily (from perl) in early 2010s (I think my first "seriously" used version was 2.6. This is mostly for system management, monitoring, and data transformation /visualisation. Nothing fancy like AI back then in a work setting.
I found the biggest impact was not so much on writing code but on it remaining readable for a very long time, even if it was created hastily "just get this working now" style. Especially in a team.
Python is still one of my favourites and the first tool I reach if bash is not enough for what I'm trying to do.
Then, in 2005, Guido van Rossum was hired by Google to work on Google Cloud. That opened the door for wider adoption in academia, since Python had strong math libraries and integrated well with tools researchers were already using, like Hadoop, right around the time big data and ML were starting to take off.
Also, between 2005 and 2006, two important things happened: Ruby on Rails came out and inspired Django, which was starting to gain popularity, and web developers were getting tired of Perl's messy syntax. That's how Python quickly became a solid choice not just for server-side scripts, but for building proper web apps. In the meantime, another language that could be embedded directly into HTML was storming the web: PHP. Its syntax was similar to JavaScript, it was easy to pick up, lowered the barrier to entry for software development, worked straight out of the box, and didn't require thousands of print statements to get things done.
The 3 Ps made history. According to programmers from 20 years ago, they were like religions. Each had its own philosophy and a loyal group of followers crusading online, getting into heated debates, all trying to win over more adopters. The new generation of devs is more pragmatic. These days it's less about language wars and more about picking the right tool for the job.
It brought across a ton of users from R and Matlab.
Pandas, Matplotlib and ScikitLearn then consolidated Python's place as the platform of choice for both academic and commercial ML.
It's very weird reading something you lived through described in these terms, as though it were being described by an anthropologist.
Can't help but wonder what the future will have to say about today.
"In 2025, programmers used 'frameworks' to hang 'apps' from some kind of 'web'. They believed these frameworks gave them magic powers. Many even fought in 'flame wars' on this topic, which experts believe involved the use of fire to destroy webs woven by competing programmers."
I feel like the religious wars aspects of this is completely overblown. The conversations around languages really hasn't changed all that much in the last 20 years. Look at the way you see things happening in HN, heck even in the comment thread right here. It's the exact same kinds of discussions as happened back 20 years ago, with exactly the same kind of pragmatism.
I think the gulf comes about from the fact that the primary sources are conversations occurring between people that are largely anonymous behind an online handle, interacting with people that aren't face to face. There's always been an element of exaggeration in the interactions. What might be a "Umm, no" with a maybe a shake of the head, becomes "Your mother was a hamster and your father smells of elderberries". Almost every party involved comes to recognise the particular cultural quirks (which varied from forum to forum) and how to translate what was said, to what was actually meant.
Yea, I was a sysadmin around 2000 (before that too) and I knew it as such.
>between 2005 and 2006, two important things happened:
Somewhat - I used it in 2001 for Plone which is based on Zope, which was somewhat popular around that time. Writing all the web stuff with Python made sense, since Plone provided a CMS and could include a wiki. Adding on some sql calls to it in python just made sense. The competition was between PHP and Python, though there were some other less popular choices. Ruby on Rails definitely was getting a lot more popular around those times. PHP didn't start getting popular around 2005, if anything, people started using Python more, and started criticizing the crappy code that was circulating in the PHP community.
In any case, it was a fun time, but what's the point of looking back like that?
I remember saying to a coworker, "Google is single-handedly keeping Python alive."
Then bam. It was everywhere. Mid 2010's, I took a cybersec job and they told me to learn Python in the two weeks between accepting and starting. "Python is all over cybersec," I was told. It was then I realized Python took over academia, which positioned it perfectly for ML. It's features made it easy to start, but it also benefited from right place, right time.
Apple also added Python in, I think, Mac OS X Jaguar, so it blipped on the radar.
When you have big players using it, the community automatically grows.
Django was the continuity of that and definitely contributed to the growing popularity of Python, but I think the hype started way before (and in fact we had to suffer Zope/Plone/Twisted for it :)).
Another decisive date was circa 2010 when the Belgian book "learn programming with python" came out. Granted, Django was already 5 years old at the time, but it brought many beginners who knew nothing about programming at the time.
I got forced to learn it for a project where I was proposing Ruby and the customer insisted on Python. This was years ago when Ruby was much slower. I was annoyed but I got used to it and here I am enjoying it many years later.
I take issue with the description and use of make though! :-D What is the point of it if you're not going to use dependencies? One might as well just write a script with a case statement..... I'm adding smileys because I don't mean to be all that serious but I really do think that the failure of the youth of today to get to grips with Make is a sad reflection on our culture....... and get off my lawn, ok? :-)
I started with this and evolved into simple flat Makefiles, because they're basically the same but Make feels more standard (there's a Makefile here vs. there's a random bash script here).
This interview from Brett Cannon (old core dev who worked on packaging, imports, the vscode python extension...) is eye opening:
https://www.bitecode.dev/p/brett-cannon-on-python-humans-and
The guy cares SO MUCH and they have so many things not to break you can feel the sense of passion and the weight of responsibility in everything he says.
I find this depressing. Not only are LLMs covertly reducing our ability to think and make decisions, they’re now also making people voluntarily conform to some lower common denominator.
It’s like humanity decided to stagnate at this one point in time (and what a bad choice of point it was) and stop exploring other directions. Only what the LLM vomits is valid.
That said, I remember writing myself a note a few years ago to avoid Python projects. I had to clean up code from all over the company and make it ready for production. Everyone had their own Python version, dependencies missing from requirements.txt, three way conflicts between 2 dependencies and the python version, wildly different styles, and a habit of pulling in as many libraries as possible [1]. Even recalling those memories makes my stomach turn.
I believe constraints make a project shine and be maintainable. I'd prefer if you throw at me a real python instead of a python project.
[1] Yes, I'm aware of containers, I was the unlucky guy writing them.
Still could be better, but I think Python's really hit its stride now.
That's kind of very optimistic evaluation - literally anything beyond "import json" will likely lead you into the abyss of virtual envs. Running something created with say Python 3.13.x on Ubuntu 22.04 or even 24.04 (LTSs) / Rocky 9 and the whole can of worms opened.
things like virtual envs + containers (docker like)/version managers become a must quickly.
My first taste of Python was as a sysadmin, back in 2012 or so, installing a service written in Python on a server. The dependency hell, the stupid venv commands, all this absolute pain just to get a goddamn webserver running, good lord. It turned me off of Python for over a decade. Almost any time I saw it I just turned and walked away, not interested, no thanks. The times I didn't, I walked right back into that pile of bullshit and remembered why I normally avoided it. The way `brew` handles it on macOS is also immensely frustrating, breaking basic pip install commands, installing libraries as commands but in ways that make them not available to other python scripts, what a goddamn disaster.
And no, I really have no clue what I'm talking about, because as someone starting out this has been so utterly stupid and bewildering that I just move on to more productive, pleasant work with a mental note of "maybe when Python gets their shit together I'll revisit it".
However, uv has, at least for my beginner and cynical eyes, swept away most of the bullshit for me. At least superficially, in the little toy projects I am starting to do in Python (precisely because its such a nicer experience), it sweeps away most of the horrid bullshit. `uv init`, `uv add`, `uv run`. And it just works*.
Say you want to use a specific version of python that is not available on Ubuntu.
1. Install build dependencies https://devguide.python.org/getting-started/setup-building/#...
2. Download whichever Python source version you want, https://www.python.org/downloads/source/. Extract it with tar
3. run ./configure --enable-optimizations --with-lto
4. run make -s -j [num cores]
5. sudo make altinstall
This will install that specific version without overwriting default system python.
You can then bash alias pip to python3.xx -m pip to make sure it runs the correct one.
All the libraries and any pip install executable will be installed locally to ~/.local folder under the specific python version.
Alternatively, if you work with other tools like node and want to manage different versions, you can use asdf, as it gives you per folder version selection.
virtual environments are really only useful for production code, where you want to test with specific versions and lock those down.
I disagree that virtual environments represent an "abyss". It takes very little effort to learn how they work [1], plus there a variety of tools that will wrap the process in various opinionated ways [2]. The environment itself is a very simple concept and requires very few moving parts; the default implementation includes some conveniences that are simply not necessary.
In particular, you don't actually need to "activate" a virtual environment; in 99% of cases you can just run Python by specifying the path to the environment's Python explicitly, and in the exceptional cases where the code is depending on environment variables being set (e.g. because it does something like `subprocess.call(['python', 'foo.py'])` to run more code in a new process, instead of checking `sys.executable` like it's supposed to, or because it explicitly checks `VIRTUAL_ENV` because it has a reason to care about activation) then you can set those environment variables yourself.
Creating a virtual environment is actually very fast. The built-in `venv` standard library module actually does it faster in my testing than the equivalent `uv` command. The slow part is bootstrapping Pip from its own wheel - but you don't need to do this [2]. You just have to tell `venv` not to, using `--without-pip`, and then you can use a separate Pip (for recent versions — almost the last 3 years now) copy cross-environment using `--python` (it's a hack, but it works if you don't have to maintain EOL versions of anything). If you need heavy-duty support, there's also the third-party `virtualenv` [3].
Much of the same tooling that manages virtual environments for you — in particular, pipx and uv, and in the hopefully near future, PAPER [4] — also does one-off script runs in a temporary virtual environment, installing dependencies described in the script itself following a new ecosystem standard [5]. Uv's caching system (and of course I am following suit) makes it very fast to re-create virtual environments with common dependencies: it has caches of unpacked wheel contents, so almost all of the work is just hard-linking file trees into the new environment.
[0]: https://stackoverflow.com/questions/76105218
[1]: https://chriswarrick.com/blog/2018/09/04/python-virtual-envi...
[2]: https://zahlman.github.io/posts/2025/01/07/python-packaging-...
[3]: https://virtualenv.pypa.io/
[4]: https://github.com/zahlman/paper
[5]: https://peps.python.org/pep-0723
Minor differences between distro versions can make a big difference, and not everyone that uses a Python script knows how to use something like pyenv to manage different versions.
Two additional suggestions:
* mise to manage system dependencies, including uv version and python itself
* just instead of make; makefile syntax is just too annoying.
Mise actually has a command runner as well which I haven't tried yet, and might work better for running commands in the context of the current environment. It's pretty nice when your GitHub actions workflow is just:
* Install mise
* mise install everything else
That said, call me old-fashioned, but I really take issue with "curl $URL | bash" as an installation method. If you're going to use an install script, inspect it first.
Sometimes that's inevitable, bit noisy of the time it isn't.
If the user is a typical consumer using a typical consumer interface, then yes you want to handhold them a bit more.
https://typer.tiangolo.com/tutorial/arguments/envvar/
It's especially nice for secrets. Best of both worlds :)
P.S. exit() is just an alias to sys.exit(), I prefer longer form.
Why is that?
Why Python for AI?
Is this referring at all to to PyTorch. If not, any guesses what the author has in mind
"Not only because the syntax is more human-friendly, but also because the Python interpreter is natively integrated in all Unix distros."
Is this referring to GNU/Linux.
UNIX (UNIX-like) includes more than Linux; some UNIX distributions do not include Python in the base system
Where it is left as choice to the user whether to install it
I know this because I use such distributions and, unless some software needs it, I do not install Python
In such case, when I am done using that software I uninstall it^1
For example, he mentions retrieving YouTube channel metadata
I do not use Python for this; I use a 19-line shell script (ash not bash), its startup time is faster
Unlike Python, it is included in the base system of the UNIX distributions (both Linux and BSD) that I use
But if I need to test something using yt-dlp, then I might temporarily install Python
1. I compile Python from source and one annoying aspect of the project , in addition to the slow startup time, is their failure to include an uninstall target in their Makefile
Ash doesn't do web requests unless you've implemented HTTP in ash. You're back to using 3rd party dependencies that aren't installed on all systems
The TCP networking is done with orginal netcat reading the HTTP from a pipe.
The TLS is handled by a TLS forward proxy listening on the loopback.
The orginal netcat and other TCP clients I use, like tcpclient from djb's ucspi or tcploop from haproxy, are not part of the NetBSD base system but are easily added when I compile the OS. For Linux I use a custom distribution I make myself, without LFS. Busybox has ash and nc together in the same binary.
These TCP client programs are stationary targets, they will work reliably year after year, and small enough that I can store and compile them quickly even on computers with modest resources. Python is constantly evolving, a moving target, and much larger.
I wrote a utility in C89 that "implements HTTP" called yy025. This is produced using GCC, specifically flex, which is intsalled on all systems I use. flex is part of the NetBSD toolchain. It's a requirement for compiling the OS. It's a requirement for building many GNU userland utilities. It's even a listed requirement when building the Linux kernel.
yy025 is what I normally use in shell scripts when I need to generate HTTP. It reads URLs on stdin and outputs customised HTTP to stdout. There is no "third party dependency" for HTTP. This is a "first party" program. I wrote it.
But this script to fetch YouTube metadata doesn't use yy025. It's just some printf statements.