Skip to content

Support dependency installation via pyproject.toml with uv #19321

@desertaxle

Description

@desertaxle

Background

Related to #18837

Users are increasingly adopting uv for dependency management, but Prefect's current execution environment setup makes it difficult to use uv effectively. The core issue is an ordering problem: Prefect needs flow code and configuration present before creating a process for flow execution.

Current workaround: Users run uv sync in pull steps after code is pulled, but this is fragile and dependent on uv configuration, potentially breaking if uv creates different virtual environments.

User desire: Be able to use uv run to execute their flows, with all dependency information defined in pyproject.toml, aligning with the Python ecosystem's standardization around pyproject.toml.

Proposed Solution

This enhancement proposes four key architectural changes:

1. Move code pulling to the Runner class

Ensures flow code and configuration are present before creating execution processes. This resolves the ordering problem by handling pull steps (including code retrieval) before spawning the flow run process.

Implementation considerations:

  • Must handle change_working_directory step carefully (use as base path rather than process-wide change)
  • Pull steps should complete before any process creation

2. Update Runner to use uv run automatically

If a pyproject.toml is present in the working directory, the Runner should automatically use uv run for flow execution. The Runner would still function as a crash observer and cancellation handler.

3. Add module entry point to flow engine

Create a new entry point: python -m prefect.flow_engine <flow_entrypoint> to allow the runner to kick off flows via uv run -m prefect.flow_engine <flow_entrypoint>.

Implementation considerations:

  • Support both module paths and file paths (e.g., /path/to/file.py:flow_name)
  • Should apply minimal @flow decorator if function isn't already decorated
  • Entry point should be similar to existing python -m prefect.engine pattern

4. Update flow engine to respect PREFECT__FLOW_RUN_ID env var

Mirror how python -m prefect.engine works, giving users the option to opt out of using a Runner by directly using uv run -m prefect.flow_engine <flow_entrypoint> via the command job variable.

Implementation considerations:

  • Should fetch flow run from API if not already provided
  • Should only occur if run context is not active (not for child flow runs)
  • Provides flexibility for advanced users who want direct control

Benefits

  • Zero configuration: "Just works" with no user changes if already using uv
  • No new interface surface area: Leverages existing patterns and tools
  • Ecosystem alignment: Provides a recommended project structure aligned with a major Python ecosystem player
  • Backward compatible: Existing deployments continue to work unchanged

Alternatives Considered

Add a --launcher option for prefect flow-run execute (Rejected)

This would allow users to specify a custom launcher command.

Why rejected: Too extensible but easy to misconfigure. Would introduce new interface surface area and potential for user error.

Create a uv sync pull step (Rejected)

Users could add a pull step that runs uv sync after code is pulled.

Why rejected:

  • Requires user action and configuration
  • Virtual environment management may not work as expected depending on uv configuration
  • Doesn't allow Python version management
  • Fragile to changes in uv behavior

User Impact

Users with existing uv projects will be able to:

  • Define dependencies in pyproject.toml (standard Python practice)
  • Push code to Git repositories
  • Have Prefect workers pull and execute flows using uv automatically
  • Manage Python versions via pyproject.toml

No changes required for users not using uv - existing deployments continue to work unchanged.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions