Hacker News new | past | comments | ask | show | jobs | submit login

Anyone use PEP 723 + uv with an LSP based editor? What's your workflow? I looked into it briefly, the only thing I saw after a lot of digging around was to use `uv sync --script <script file>` and get the venv from the output of this command, activate that venv or specify it in your editor. Is there any other way, what I describe above seems a bit hacky since `sync` isn't meant to provide the venv path specifically, it just happens to display it.

Edit: I posted this comment before reading the article. Just read it now and I see that the author also kinda had a similar question. But I guess the author didn't happen to find the same workaround as I mention using the `sync` output. If the author sees this, maybe they can update the article if it's helpful to mention what I wrote above.






uv v0.6.10 has just been released with a more convenient way of doing this:

    uv python find --script foo.py
https://github.com/astral-sh/uv/releases/tag/0.6.10

https://docs.astral.sh/uv/reference/cli/#uv-python-find--scr...


How does it work ? How does it find the environment ?

Let say I have a project in `/home/boumtac/dev/myproject` with the venv inside.

If I run `uv python find --script /home/boumtac/dev/myproject/my_task.py`, will it find the venv ?


The philosophy of uv is that the venv is ephemeral; creating a new venv should be fast enough that you can do it on demand.

Do you have a standalone script or do you have a project? --script is for standalone scripts. You don’t use it with projects.

If you tell it to run a standalone script, it will construct the venv itself on the fly in $XDG_CACHE_HOME.

If you have a project, then it will look in the .venv/ subdirectory by default and you can change this with the $UV_PROJECT_ENVIRONMENT environment variable. If it doesn’t find an environment where it is expecting to, it will construct one.


Thanks! Came here to ask how to make pyright work with uv scripts...

pyright --pythonpath $(uv python find --script foo.py) foo.py



My general solution to project management problems with PEP 723 scripts is to develop the script as a regular Python application that has `pyproject.toml`. It lets you use all of your normal tooling. While I don't use an LSP-based editor, it makes things easy with Ruff and Pyright. I run my standard Poe the Poet (https://poethepoet.natn.io/) tasks for formatting, linting, and type checking as in any other project.

One drawback of this workflow is that by default, you duplicate the dependencies: you have them both in the PEP 723 script itself and `pyproject.toml`. I just switched a small server application from shiv (https://github.com/linkedin/shiv) to inline script metadata after a binary dependency broke the zipapp. I experimented with having `pyproject.toml` as the single source of truth for metadata in this project. I wrote the following code to embed the metadata in the script before it was deployed on the server. In a project that didn't already have a build and deploy step, you'd probably want to modify the PEP 723 script in place.

  #! /usr/bin/env python3
  # License: https://dbohdan.mit-license.org/@2025/license.txt
  
  import re
  import tomllib
  from pathlib import Path
  from string import Template
  
  import tomli_w
  
  DEPENDENCIES = "dependencies"
  PROJECT = "project"
  REQUIRES_PYTHON = "requires-python"
  
  DST = Path("bundle.py")
  PYPROJECT = Path("pyproject.toml")
  SRC = Path("main.py")
  
  BUNDLE = Template(
      """
  #! /usr/bin/env -S uv run --quiet --script
  # /// script
  $toml
  # ///
  
  $code
  """.strip()
  )
  
  
  def main() -> None:
      with PYPROJECT.open("rb") as f:
          pyproject = tomllib.load(f)
  
      toml = tomli_w.dumps(
          {
              DEPENDENCIES: pyproject[PROJECT][DEPENDENCIES],
              REQUIRES_PYTHON: pyproject[PROJECT][REQUIRES_PYTHON],
          },
          indent=2,
      )
  
      code = SRC.read_text()
      code = re.sub(r"^#![^\n]+\n", "", code)
  
      bundle = BUNDLE.substitute(
          toml="\n".join(f"# {line}" for line in toml.splitlines()),
          code=code,
      )
  
      DST.write_text(bundle)
  
  
  if __name__ == "__main__":
      main()

If you already have a pyproject.toml, and a "build and deploy step", why not just package normally? PEP 723 was developed for the part of the Python world that doesn't already live on PyPI (or a private package index).

I probably should! My motivation early into the project was to try different ways to distribute a TUI app in Python and see how practical they were.

I started with the most self-contained, Nuitka. I quickly switched to building a zipapp with shiv because it was faster and cross-platform if you avoided binary dependencies. I wanted to be able to share a Python application with others easily, especially with technical users who weren't heavily into Python. PEP 723 added the ability for those hypothetical users to inspect the app and modify it lightly with minimum effort. But since I am still the sole user, I can just build a wheel and install it with `uv tool install` on the server.




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: