Hacker News new | ask | show | jobs
by quickthrower2 974 days ago
Is there a way to compile a python CLI script, and it’s dependencies and python itself into an executable.

That makes the tool nicer to use. To me a CLI tool should stand alone ideally. Obviously that is not the trend as many things that are CLI are installed via node or npm.

I guess docker could solve most of the issues here

8 comments

The answer is "sometimes".

Python can be relatively easily embedded in a C program and its source code can be compiled to C. The problems come from Python modules that are built to use shared libraries. It's not impossible to solve, but it means that you'd have to find the source code for those modules and recompile them to link statically with those libraries. This could be quite an undertaking, and is probably not worth it, unless you want to learn more about build systems and build tools in general.

Finally, in some cases it's impossible due to the licensing. I.e. you may have a Python module that relies on a shared library with license that prohibits redistribution. In that case it's not a technical, but a legal problem. This, however, isn't unique to Python, and you'd face similar issues no matter the language you chose to use.

Re' Docker: in most cases this is not a solution to making command-line interfaces. I actually struggle to think in what case it is. You'd have to write a program with the command-line interface and then put it in the image for Docker to create a container from (which will usually make it very inconvenient to use due to the Docker containers by default running such programs in separate filesystem, user and network interfaces.) This would make things like user identity, user's data and, well, obviously, network hard to access for the program while gaining you noting of substance.

Yeah! pyinstaller is an example. They do it by bundling a standalone python interpreter (x-platform ones too) with the necessary python libraries bundled in, just like you suggested
I recommend pipx (https://pypa.github.io/pipx/) for this to get the same basic result. While it's not a pre-compiled binary, it is a standalone installation that takes care of dependencies and virtual virtual environments in a way that the user never has to think about them. As far as they're concerned, they `pipx install ...` and it "just works".
What if you are on Python 3.10 and the Python code was built using Python 3.11 features? I don't think `pipx` would work in that case.
IIRC pipx uses your local Python version. So in your example, you'd need to `pipx install` while py 3.11 was active.

Certainly not ideal, but I find it's unusual for a tool to require a super-new version. Plus, `pyenv` makes it easy enough to install multiple versions in parallel and run commands under specific versions.

Sure, it would be better if this whole process wasn't so complicated, but I find it's pretty workable overall.

You'd need to install 3.11 first. When installing a package with pipx you can specify what other Python installation to use, if it's not the default one.
By default, pipx use the python it's installed with, but you can change the python interpreter for each installed application.
There are a few tools that can do this. I've had good initial results from PyInstaller: https://til.simonwillison.net/python/packaging-pyinstaller
You better off with using a compiled language.

If you interested in a language that's compiled, fast, but as easy and pleasant as Python - I'd recommend you take a look at Nim: https://nim-lang.org.

Nim has cligen library to generate and parse arguments: https://github.com/c-blake/cligen

And to prove what Nim's capable of - here's a cool repo with 100+ cli apps cligen author wrote in Nim: https://github.com/c-blake/bu

cligen also allows End-CL-users to adjust colorization of --help output like https://github.com/c-blake/cligen/blob/master/screenshots/di... using something like https://github.com/c-blake/cligen/wiki/Dark-BG-Config-File

Last I knew, the argparse backing most Py CLI solutions did not support such easier (for many) to read help text, but the PyUniverse is too vast to be sure without much related work searching.

Containers are the strategy I've used in the past for this purpose. For my needs, I've found any extra runtime to be negligible.
It's the main reason for Go's popularity imho. I loved the fact that all the Hashicorp stuff i used (consul, packer, vault, terraform) were just binaries.
Maybe one day, Mojo