4 ms·
Very interesting write-up, I'm glad to see a core developer thinking deeply on this topic because Python has a lot of room for improvement. This touches briefl
by EvanPlaice 11y ago
Very interesting write-up, I'm glad to see a core developer thinking deeply on this topic because Python has a lot of room for improvement.
This touches briefly on 1 of 3 major issues I have with python. I'll try my best to articulate them from smallest-to-greatest impact.
1. import semantics
It would be amazing to see the import module be abstracted out of the sys module. Not just for the reasons mentioned in the article. Ideally, it would allow developers to override/extend the implementation of import and experiment with new ways to handle.
For instance, why can't a developer write a module to experiment with using es6-module style imports.
```
import {attr1, attr2} from module@[version]/submodule
import * from module2
```
When I wrote the pypreprocessor lib, I simply wanted to add the ability to import and conditionally-compile code using inline c-style preprocessor directives. It works by blocking the import, preprocessing the code, then importing the postprocessed version of the code.
Implementing it is ugly because there's no way to inline the preprocessor step. If I had the ability to extend and inline the preprocessor step as a custom import module, the specifics would be transparent to the user.
With a preprocessor it would be possible to write python2/python3 code side-by-side making the transition much easier for library developers. Implementing it as a custom import add-on would allow developers to extend the platform without polluting core (ie since GvR is vehemently against adding preprocessor capability to core).
Why does python default to the mentality of 'one true way'? There is a huge ecosystem of developers willing to build/extend and experiment with the language in ways that aren't immediately apparent to core design committee.
2. Packages violates 'Explicit is better than implicit'
Package management as a whole is a terrible, broken experience for library developers and consumers of those libraries alike. Global-only package installations, dependency hell, lack of version configuration, inability to automate dependency loading, etc.
"Vendoring is not hard thanks to relative imports and most projects don't seem to need it."
I highly disagree. Expecting users to either install dependencies globally or manually copy them to the package contents sucks. The former introduces potential environmental-level side effects such as dependency conflicts and requires virtualenv to isolate packages. The latter is prone to error, adds maintenance overhead as dependencies are updated, and makes it unclear to developers who want to add dependencies without polluting source control.
Just look at the NPM ecosystem for inspiration. Vendoring, incl versioned dependency management is done on a per-project level by default and the benefits are clear. I can execute `npm install` from the CLI and the package manager will download+install all of a projects dependencies (ie and dependencies of dependencies) automagically. There's a reason the NPM eclipsed every other packaging ecosystem in such a short period. It 'just works'.
Virtualenv is a hack. Instead of supporting package-level dependencies, it forces developers to limit the environment to the package-level. It introduces all of the same problems inherent to using globally installed dependencies, except at a local level.
This violates II of 'The Twelve Factor App'
http://12factor.net/dependencies http://12factor.net/dependencies
Pets vs Cattle
While the current model works well with 'pets', ie long-running processes and persistent environments. It causes a lot of problems when it comes to 'cattle', ie transient/disposable environments because it requires developers to re-create an identical copy of the development environment on the target for every deployment. Not only does this add a lot of provisioning overhead/complexity but is highly prone to error if/when the environment changes (ex modules added, configuration changes).
DevOps is hard enough, even without the overhead of cloning environment-specific details of the language platform.
3. Religious adherence to 'the one true way'
Specifically, python is a platform implementation when it 'should' be a language.
Don't get me wrong, Python is a significant improvement over the everything-and-the-kitchen-sink approach used by platforms like .NET/Java. I understand the need for including enough core functionality to get users up and running quickly. What I don't agree with is the difficulty of extending/overriding the default functionality.
Along those lines, I'd include a requirements:
- expose the core modules as classes (ie not just import) that can be extended/overridden
- take some time to engineer a really good package management tool
- setup.py shouldn't require hand-coding, pip should be capable of generating it
- unify the configuration at the package-level
- additional package install steps can be added as pre/post hooks in the configuration
-------
I have some obvious biases that come from the JS/Node.js development community. Don't get me wrong, I love python as a language and will continue to use it in the distant future. Without good package/version management I don't see it as a good alternative for building anything but trivial applications.
- andybak 11y agoGood post but I call hyperbole on one of your closing remarks: > Without good package/version management I don't see it as a good alternative for building anything but trivial applications. Even if we agree Python has mediocre package management then it is still more of an annoyance/hinderance than a factor that realistically rules out "building anything but trivial applications".
- EvanPlaice 11y agoYou're right. Python is definitely useful for more than 'trivial applications'. My statement was more a matter of subjective personal preference. The emphasis on package management isn't so much about building non-trivial applications as it is about deploying non-trivial applications. My ideal is a system that can be built in a composable manner using the standard tools. A deployment would include: - cloning the source - installing dependencies - setting env vars - running tests - launching the application It should be trivial to repeat this process to deploy to multiple targets as well as automate continuous integration testing. With the current tool chain there's no clear path to accomplish this without relying on a higher level abstraction like Docker.