This is my absolute favourite uv features and the reason I switched to uv.
I have a bunch of scripts in my git-hooks which have dependencies which I don't want in my main venv.
#!/usr/bin/env -S uv run --script --python 3.13
This single feature meant that I could use the dependencies without making its own venv, but just include "brew install uv" as instructions to the devs.
Save that as script.py and you can use "uv run script.py" to run it with the specified dependencies, magically installed into a temporary virtual environment without you having to think about them at all.
Claude 4 actually knows about this trick, which means you can ask it to write you a Python script "with inline script dependencies" and it will do the right thing, e.g. https://claude.ai/share/1217b467-d273-40d0-9699-f6a38113f045 - the prompt there was:
Write a Python script with inline script
dependencies that uses httpx and click to
download a large file and show a progress bar
How do you never learn? No, honestly, how do you never learn this simple thing: it will break! I will bet my pension on that it will break, and perhaps not you, but some hundreds of developers will have to try to debug and try to figure out where the dependencies went and why they weren't installed correctly, or why something was missing and so on.
There will never be a situation that you don't have to think about something as important as dependencies at all.
I'm not a Python dev, but had to write a script the other day and got all cought up with the virtual env stuff. Why can't `uv` just infer the dependencies from the `import ...` line? Why declare the dependencies twice?
Why doesn't pip support PEP 723? I'm all for spreading the love of our lord and savior uv, but it should be necessary to have an official implementation.
It's completely out of scope for pip, which is purely about modifying the set of packages installed into non-transient environments.
Pipx is a wrapper that does more or less what you're looking for (including PEP 723 support), but it arbitrarily refuses to process top-level packages unless they specify an entry point (which makes them "applications" even with abstract dependencies).
I'm planning to support it in PAPER, which can roughly be described as my vision of what pip and pipx, taken together, should have been.
Oh this looks amazing! I had pretty much stopped using Python for my one-off scripts because of the hassle of dependencies. I can't wait to try this out.
Oh nice, I was already a happy user of the uv-specific shebang with in-script dependencies, but the `uv lock --script example.py` command to create a lock file that is specific to one script takes it to another level! Amazing how this feels so natural and yet only appeared after 20+ years of Python packaging.
Note that this only works for single-file scripts.
If you have a project with modules, and you'd like a module to declare its dependencies, this won't work. uv will only get those dependencies declared in the invoked file.
It’s a pretty minimal wrapper around “uv” and “iPython” to provide the functionality from the article, but for Jupyter notebooks. It’s similar to other projects, but I think my implementation is the least intrusive and a good “citizen” of the Jupyter ecosystem.
Which provides a companion Jupyter plugin to manage the embedded script dependencies of noteboooks with a UI. Warning — this one is partially vibe-coded and very early days.
How many package managers can one language have? Its a simple language but setting it up is just incredibly bad. Maybe this is the one or should I wait for the next?
I hate such poor docs that don't explain how things work, and instead prefer hiding behind some "magic".
> Constraints can be added to the requested dependency if specific versions are needed:
> uv run --with 'rich>12,<13' example.py
Why not mention that this will make uv download specified versions of specified packages somewhere on the disk. Where? Are those packages going to get cached somewhere? Or will it re-download those same packages again and again every time you run this command?
This is pretty great. Passing python code out to my students is usually also confronted with the question of "How do I run it?", which is usually terrible to answer. Now, I can just tell them to get uv (single command) and run it.
One gotcha I caught myself in with this technique is using it in a script that would remediate a situation where my home has lost internet and needed the router to be power cycled. When the internet is out, `uv` cannot download the dependencies specified in the script, and the script would fail. Thankfully I noticed this problem after writing it but before needing it to actually work, and refactored my setup to pre-install the needed dependencies. But don't make the same mistake I almost made! Don't use this for code that may need to run airgapped! Even with uv caching you may still get a cache miss.
Love this feature of UV. Here's a one-liner to launch jupyter notebook without even "installing" it:
uv run --with jupyter jupyter notebook
Everything is put into a temporary virtual environment that's cleaned up afterwards. Best thing is that if you run it from a project it will pick up those dependencies as well.
I wish there was a straightforward way to let VS Code pick up the venv that uv transparently creates.
Out of the box, the Python extension redlines all the third-party imports.
As a workaround, I have to plunge into the guts of uv's Cache directory to tell VS Code the cached venv path manually, and cross fingers that it won't recreate that venv too often.
I recently found a small issue with `uv run`. If you run a script from outside the project folder, it looks for the pyproject.toml on the folder from which you are calling `uv run`, not on the folder where the python script is located (or its parents)! Because of that scripts that store their dependencies in a pyproject.toml cannot be run successfully using a “bare” `uv run path/to/my/script.py` from outside the project folder.
You can work around this surprising behavior by always using inline dependencies, or by using the `--project` argument but this requires that you type the script path twice which is pretty inconvenient.
Other than that uv is awesome, but this small quirk is quite annoying.
One case this may not work well is when one of the dependencies is Pytorch. Uv has explicit support for Pytorch ( https://docs.astral.sh/uv/guides/integration/pytorch/ ) but with the script headers I don't see a way to pick the most appropriate wheel index (cpu vs cuda vs rocm)
There are a lot of bits and pieces that are clicking into place lately in the Python ecosystem. Recently I've been using the combination of Marimo and these uv script dependencies for building reproducible rwporting and diagnostic tooling for other teams.
> Python doesn't require a requirements.txt file, but if you don't maintain this file, or neglect to provide one, it could result in broken functionalities - an unfortunate circumstance for a scripting language.
42 comments
[ 4.8 ms ] story [ 61.0 ms ] threadI have a bunch of scripts in my git-hooks which have dependencies which I don't want in my main venv.
#!/usr/bin/env -S uv run --script --python 3.13
This single feature meant that I could use the dependencies without making its own venv, but just include "brew install uv" as instructions to the devs.
It's an implementation of Python PEP 723: https://peps.python.org/pep-0723/
Claude 4 actually knows about this trick, which means you can ask it to write you a Python script "with inline script dependencies" and it will do the right thing, e.g. https://claude.ai/share/1217b467-d273-40d0-9699-f6a38113f045 - the prompt there was:
Prior to Claude 4 I had a custom Claude project that included special instructions on how to do this, but that's not necessary any more: https://simonwillison.net/2024/Dec/19/one-shot-python-tools/Hahahahaha.
Oh. I'm rolling on the floor. Hahahahaha.
How do you never learn? No, honestly, how do you never learn this simple thing: it will break! I will bet my pension on that it will break, and perhaps not you, but some hundreds of developers will have to try to debug and try to figure out where the dependencies went and why they weren't installed correctly, or why something was missing and so on.
There will never be a situation that you don't have to think about something as important as dependencies at all.
Pipx is a wrapper that does more or less what you're looking for (including PEP 723 support), but it arbitrarily refuses to process top-level packages unless they specify an entry point (which makes them "applications" even with abstract dependencies).
I'm planning to support it in PAPER, which can roughly be described as my vision of what pip and pipx, taken together, should have been.
If you have a project with modules, and you'd like a module to declare its dependencies, this won't work. uv will only get those dependencies declared in the invoked file.
For a multi-file project, you must have a `pyproject.toml`, see https://docs.astral.sh/uv/guides/projects/#managing-dependen...
In both cases, the script/project writer can use `uv add <dependency>`, just in the single-file case they must add `--script`.
https://github.com/tobinjones/uvkernel
It’s a pretty minimal wrapper around “uv” and “iPython” to provide the functionality from the article, but for Jupyter notebooks. It’s similar to other projects, but I think my implementation is the least intrusive and a good “citizen” of the Jupyter ecosystem.
There’s also this work-in-progress:
https://github.com/tobinjones/pep723widget
Which provides a companion Jupyter plugin to manage the embedded script dependencies of noteboooks with a UI. Warning — this one is partially vibe-coded and very early days.
Fun with uv and PEP 723
640 points | 227 comments
> Constraints can be added to the requested dependency if specific versions are needed:
> uv run --with 'rich>12,<13' example.py
Why not mention that this will make uv download specified versions of specified packages somewhere on the disk. Where? Are those packages going to get cached somewhere? Or will it re-download those same packages again and again every time you run this command?
uvx marimo edit
A one liner with marimo that also respects (and records) inline script metadata using uv:
uvx marimo edit --sandbox my_notebook.py
https://docs.astral.sh/uv/guides/integration/marimo/
this is neat af. my throw-away scripts folder will be cleaner now.
https://gist.github.com/pythoninthegrass/e5b0e23041fe3352666...
tl;dr
Installs 3 deps into the uv cache, then does the following:
1. httpx to call get request from github api
2. sh (library) to run ls command for current directory
3. python-decouple to read an .env file or env var
Out of the box, the Python extension redlines all the third-party imports.
As a workaround, I have to plunge into the guts of uv's Cache directory to tell VS Code the cached venv path manually, and cross fingers that it won't recreate that venv too often.
You can work around this surprising behavior by always using inline dependencies, or by using the `--project` argument but this requires that you type the script path twice which is pretty inconvenient.
Other than that uv is awesome, but this small quirk is quite annoying.
> Python doesn't require a requirements.txt file, but if you don't maintain this file, or neglect to provide one, it could result in broken functionalities - an unfortunate circumstance for a scripting language.
https://twitter.com/_damnever/status/1697247813854503250