... it's tricky. In Java there's a cultural expectation that you name a package like
package organization.dns.name.this.and.that;
but real scalability in a module system requires that somebody else packages things up as
package this.and.that;
and you can make the system look at a particular wheel/jar/whatever and make it visible with a prefix you specify like
package their.this.and.that;
Programmers seem to hate rigorous namespace systems though. My first year programming Java (before JDK 1.0) the web site that properly documented how to use Java packages was at NASA and you still had people writing Java classes that were in the default package.
But let's all be real here: the ability of __init__.py to do FUCKING ANYTHING IT WANTS is insanity made manifest
I am kind of iffy on golang's import (. "some/packge/for/side-effects") but at least it cannot suddenly mutate GOPATH[0]="/home/jimmy/lol/u/fucked" as one seems to be able to do on the regular with python
I am acutely aware that is (programmer|package|organization|culture)-dependent but the very idea that one can do that drives us rigorous people stark-raving
It took me a while to realize that you do mean __init__.py running when a package imports.
But, you know, top-level code (which can do anything) runs when you import any Python module (the first time), and Python code doesn't have to be in a package to get imported. (The standard library depends on this.)
That. Forcing people to do it right from day one helps a lot. Also Rust attracts a programmer who is willing to accept some pain up front to save pain later, if your motto is "give me convenience or give me death" you might stick with C or Python.
If you give people an "easy way out" it is very hard to compel them to do it more rigorously. Look at the history of C++ namespaces as well as the non-acceptance of various "Modula" languages and Ada back in the 1980s.