What about Ruby, Rust, or Go, for example?
What about Ruby, Rust, or Go, for example?
Instead, Python is developing a set of interoperable standards and APIs that any number of build and packaging tools can use. So projects can choose whatever build tool makes sense for them, and and users can build any project via a uniform interface.
As an example, let's say that I am writing a web app which serves a machine learning model. I have three dependencies: a web framework, a database driver, and a machine learning framework. The web framework might be packaged using Flit, the database driver might be packaged using Setuptools, and the ML framework might be packaged using CMake or Meson. And for my own project I might choose to use Hatch or Poetry. When I use Pip to install my dependencies, the details of what tool they were packaged with are completely abstracted away. Even if I need to compile something because there is no binary package published for my system, Pip will automatically install the required build dependencies in an isolated environment, and it will magically know how to build the package, using nothing but the package's own declaration of its "build backend". And then when I want to publish my own work, and users will have the same experience when they need to install my dependencies.
The system doesn't work 100% perfectly in all cases (mostly due to things that are out of scope, like managing shared libraries at the system level), but it actually works most of the time for most people in most situations. And they were no doubt issues transitioning from older systems. But as far as I know, no system like this has ever even been attempted, let alone rolled out to millions of users and working so seamlessly that most people didn't even realize it was happening.
So it's not perfect. And maybe the whole idea is backwards and would've been avoided if there had been a single coherent package management story in the first place. But given the scale of the challenge, I think we should all be a little less eager to wave the "Python steering council is stupid & bad" banner.
0. Java was designed to be fast enough to be comparable with C/C++. Think 2x slower or less, not 10-100x slower. This leads to:
1. Most Java libraries are in Java, they're not native. And they're portable as-is across platforms. If they do have platform specific code, it's their job to make sure they bundle and load everything needed for the specific problem.
2. In 2004 Maven 1 was launched, then in 2005 Maven 2 came with a repository format update. Packages are zip files called jars (Java ARchive), there are also wars (Web ARchive) which are zip-of-zips meant to be unpacked by the application server before the first launch, or ear (Enterprise ARchive), which are also zip-of-zips but I forget the exact details for using these.
3. The Maven repo format is the same, locally and remotely. When you work with Maven (or Gradle, or any Java build tool, since they're ALL compatible with Maven, otherwise nobody would use them), you get a local cache/mirror/proxy of the remote repos.
4. Because Java has CLASSPATH (sort of like PYTHONPATH but probably better, and it probably inspired PYTHONPATH because I'm sure the Java CLASSPATH predates it), packages are not copied over to the local folder when developing. Maven & co just assemble the correct CLASSPATH and everything is referred to directly from the local repo. You don't have venvs or node_modules because those are just silly hacks that aren't needed here.
5. If you need to package Java stuff, the standard approaches are:
- cross platform jars for libraries (these are usually published to the Maven repo and can be used natively by any Java package manager)
- zips for desktop apps; shell scripts or executable launchers inside the zips to launch the apps
- wars for web applications
- ears for huge, enterprise applications
It's obviously very deep and complex when you want to look at everything, but that's it.
Because Java is really close to "Write Once, Run Anywhere" in practice, for most platforms yeah, you just copy over the jar/zip.
The hardest part that people complain is installing the JRE, which is SUPER silly since for a technical person it should be trivial to do.
For non technical person, since at least 10 years ago, you can just bundle the JRE with your app. These days (at least 5+ years), I'm fairly sure you can AOT compile the app, even.
Python, by comparison, is a horror show.
And it all comes from 0. -> Python is slow, it was meant to be used with C libraries, so it carries all the baggage from that ancient and creaky ecosystem. Packaging a Python (or Ruby, or...) app to deploy on Windows, Linux (multiple distros), MacOS is such a horror show that they invented an entire layer with Docker, to just put the whole thing into an almost literal shipping container and not bother with the craziness inside.
Just pointing out that Python predates Java by a few years. Not sure when the PATH concept was introduced, though.
I don't know the exact chronology of CLASSPATH versus PYTHONPATH, but I can tell you that CLASSPATH usage is pervasive and has been so from the start, for Java (I was using Maven 2 in 2007 and even then CLASSPATH was established, being also used by the Ant and Eclipse and other, older, tools), while PYTHONPATH is definitely not used to the same effect in Python, it's an afterthought.