#!/usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.11"
# dependencies = [ "modules", "here" ]
# ///
The script now works like a standalone executable, and uv will magically install and use the specified modules. #!/usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.11"
# dependencies = [ "modules", "here" ]
# ///
The script now works like a standalone executable, and uv will magically install and use the specified modules.But whoever runs this has to install uv first, so not really standalone.
"Lol, no I break into computer systems I am a hacker"
"Geeze hell no I have an axe, I am an OG hacker"
I could totally see `#!/usr/bin/python723` become a thing :)
The two main runners I am aware of are uv and pipx. (Any compliant runner can be referenced in the shebang to make a script standalone where shebangs are supported.)
Small price to pay for escaping python dependency hell.
It will install and use distribution packages, to use PyPA's terminology; the term "module" generally refers to a component of an import package. Which is to say: the names you write here must be the names that you would use in a `uv pip install` command, not the names you `import` in the code, although they may align.
This is an ecosystem standard (https://peps.python.org/pep-0723/) and pipx (https://pipx.pypa.io) also supports it.
linux core utils have supported this since 2018 (coreutils 8.3), amusingly it is the same release that added `cp --reflink`. AFAIK I know you have to opt out by having `POSIX_CORRECT=1` or `POSIX_ME_HARDER=1` or `--pedantic` set in your environment. [1]
freebsd core utils have supported this since 2008
MacOS has basically always supported this.
---
1. Amusingly despite `POSIX_ME_HARDER` not being official a alrge swapt of core utils support it. https://www.gnu.org/prep/standards/html_node/Non_002dGNU-Sta...
This isn't a knock against UV, but more a criticism of dynamic dependency resolution. I'd feel much better about this if UV had a way to whitelist specific dependencies/dependency versions.
uv installing deps is hardly more risky.
uv executes http://somemirror.com/some-version
most people like their distro to vet these things. uv et all had a reason when Python2 and 3 were a mess. i think that time is way behind us. pip is mostly to install libraries, and even that is mostly already done by the distros.
Scanning for external dependencies is common but not so much internal private libraries.
I've used Tiger/Saint/Satan/COPS in the distant past. But I think they're somewhat obsoleted by modern packaging and security like apparmor and selinux, not to mention docker and similar isolators.
If you don't care about being ecosystem-compliant (and I am sure malware does not), it's only a few lines of Python to download the code and eval it.
But it’s much harder to inspect what the imports are going to do and be sure they’re free of any unsavory behavior.
I meant it’s easy to inspect your script’s logic — look it. Bunch harder to audit the code in dependencies though…
It’s the script contents that count, not just dependencies.
Deno-style dependency version pinning doesn’t solve this problem unless you check every hash.
curl -LsSf https://astral.sh/uv/install.sh | sh """
Also isn't great. But that's how homebrew is installed, so ... shrug ... ?
Not to bash uv/homebrew, they are better than most _easy_ alternatives.
But then I'm a weirdo that takes personal offense at tools hijacking my rc / PATH, and keep things like homebrew at arm's length, explicitly calling shellenv when I need to use it.
I will happily copy-paste this from any source I trust, for the same reason I'll happily install their software any other way.
For anything that I want to depend on, I prefer stronger auditability to ease of install. I get it, theoretically you can do the exact same thing with curl/sh as with git download/inspecting dependencies, installing the source and so on. But in reality, I'm lazy (and per another thread, a 70s hippie) and would like to nix any temptation to cut corners in the bud.
(sadly, uv cannot detect the release date of some packages. I'm looking at you, yaml!)
I want to be able to ship a bundle which needs zero network access to run, but will run.
It is still frustratingly difficult to make portable Python programs.
My current hobby language is janet. Creating a statically linked binary from a script in janet is trivial. You can even bring your own C libraries.
Although several variations on this theme already exist, I'm sure. https://github.com/pex-tool/pex/ is arguably one of them, but it's quite a bit bulkier than what I'm looking for.
The man page tells me:
-S, --split-string=S
process and split S into separate arguments; used to pass multi‐
ple arguments on shebang lines
Without that, the system may try to treat the entirety of "uv run --script" as the program name, and fail to find it. Depending on your env implementation and/or your shell, this may not be needed.-S causes the string to be split on spaces and so the arguments are passed correctly.
So in fact "-S" is not passed as a separate argument, but as a prefix in the first (and only) argument, and env then extracts it and acts accordingly:
``` $ /usr/bin/env "-S echo deadbeef" deadbeef ```
As long as you have internet access, and whatever repository it's drawing from is online, and you may get different version of python each time, ...
But, yes, python scripts with in-script dependencies plus uv to run them doesn't change dependency distribution, just streamlines use compared to manual setup of a venv per script.