8000 Enhanced support for uv dynamic virtual environments in Prefect agent executions · Issue #18181 · PrefectHQ/prefect · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Enhanced support for uv dynamic virtual environments in Prefect agent executions #18181

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
eduardojandre opened this issue May 27, 2025 · 3 comments
Labels
enhancement An improvement of an existing feature

Comments

@eduardojandre
Copy link
eduardojandre commented May 27, 2025

Describe the current behavior

Currently, Prefect agents execute flows using the environment in which the agent process is running. While this works well in homogeneous environments, it complicates scenarios where different flows require distinct Python environments or dependency sets.

The current alternatives — using multiple agent configurations or dynamically instantiated containers with specialized images — introduce additional operational complexity, infrastructure overhead, and slower startup times.

Describe the proposed behavior

Proposed Behavior
Introduce a mechanism within the Prefect agent or flow runner that allows:

  • Optional detection of a .venv or uv environment in the cloned repository.
  • Invocation of the virtual environment's Python binary to execute the flow, instead of relying on the agent's global Python environment.

Potential Implementation Ideas

  • Modify src/prefect/workers/process.py (ProcessWorker) to support automatic detection of a .venv or uv environment in the cloned repository.
    If such an environment exists, the worker can invoke the flow run using the Python binary within that virtual environment, instead of the agent's default sys.executable.

  • Consider extending similar logic to other workers to support it, ensuring consistent behavior across different deployment types, including containerized and Kubernetes-based workers.

  • Provide a configuration option (e.g., environment variable or deployment setting) to enable or disable this auto-detection and invocation of virtual environments, allowing for flexible adoption.

Example Use

An organization operates a Prefect agent on a shared server where multiple teams deploy flows with different and potentially conflicting dependencies.

With this feature, each team can commit their flow code, and use a Utility step on the pull action to create a dedicated .venv or uv environment within their repository. When the flow is deployed and executed by the agent:

  1. The agent clones the repository
  2. Agent runs Utility step to generate virtual env
  3. The and detects the presence of the virtual environment, and instead of using the agent's global Python interpreter, it automatically invokes the flow using the python binary inside the detected environment.
  4. This allows different flows to run with completely isolated dependencies without requiring multiple agents or complex container orchestration.
    For example:
  • Flow A requires pandas==1.5.
  • Flow B requires pandas==2.2.

Both flows can run independently on the same agent using their respective virtual environments, improving deployment flexibility and minimizing dependency conflicts.

Additional context

Benefits

Simplified and Faster Iteration

Switching Python environments via virtual environments (venv, uv, etc.) can be faster and simpler than building, pushing, and managing container images. Developers can adjust dependencies without modifying deployment infrastructure.

Additionally, execution startup time can be significantly reduced on some scenarios — invoking a subprocess using the environment's Python binary is can be faster than instantiating a new container. This makes the approach particularly well-suited for short-lived flows or frequent deployments.

Greater Flexibility in Deployment

Enables the use of multiple Python environments within a single worker, allowing diverse flows with different dependencies to coexist without requiring container orchestration.

Improved Compatibility

Supports scenarios where running inside a container is restricted,

@eduardojandre eduardojandre added the enhancement An improvement of an existing feature label May 27, 2025
@zzstoatzz
Copy link
Collaborator
zzstoatzz commented May 27, 2025

hi @eduardojandre - thanks for the write-up! this is possible today by overriding the command job variable on a per deployment basis like this. you can also run arbitrary shell commands in a pull step instead to setup your flow run venv as needed.

Modify src/prefect/workers/process.py (ProcessWorker) to support automatic detection of a .venv or uv environment in the cloned repository.

we are unlikely to do this, because the above escape hatch already exists and there is a great deal of variation on what "automation detection" could mean here

additionally, you might be interested in ad-hoc infra submission.

docs: https://docs.prefect.io/v3/deploy/submit-flows-directly-to-dynamic-infrastructure
issue: #17194

given the optionality that exists today and the documented plans to expand ad-hoc infra over time, I think we can close this issue. what do you think?

@eduardojandre
Copy link
Author

Hi @zzstoatzz, thank you very much for the super quick response!

I appreciate the flexibility that Prefect offers with command overrides and pull steps. I had actually been experimenting with something along those lines, but I ran into a limitation: the pull step seems to execute after the command, which makes it tricky for my use case.

Specifically, I was trying to set up something like this:

deployments:
  - name: test-labs-uv4
    ...
    pull:
      - prefect.deployments.steps.git_clone:
          id: clone-step
          repository: "https://dev.azure.com/prefect-demo/_git/prefect-demo"
          branch: "testeduardo"
          access_token: "{{ prefect.blocks.secret.azure-devops-token }}"
      - prefect.deployments.steps.run_shell_script:
          script: |
            uv venv .venv
            uv pip install -r requirements.txt
    work_pool:
      name: my-work-pool
      job_variables:
        command: "uv run -m prefect.engine"

But since the repo isn’t cloned yet when command runs, the environment isn’t available, so this approach doesn’t quite solve the problem I’m aiming to address.

I completely understand the concern about generalizing "automatic detection," especially given the variations in environments. I also looked into ad-hoc infrastructure submission as you suggested — while it’s a great feature, it doesn’t quite fit my use case either.

My use case is to support lightweight flows with slightly different dependency requirements, all running on the same worker, without having to manage and provision entire container images for each variation. I also understand what I proposed as a solution will not work either because of the order.
But I think the use case is still valid and we might find another way of doing. maybe a pre pull action where we download and install requirements.

Thanks again!

@zzstoatzz
Copy link
Collaborator
zzstoatzz commented May 28, 2025

hi @eduardojandre - you shouldn't need both. you're correct about the sequencing, but I'm suggesting you could either

  • override command if you want to point at a repo or existing package (use --with)
  • setup a venv as needed in a pull step if you want to install from cloned requirements

in this case it sounds like you'd prefer the latter, so check out this example:

» prefect deployment run 'uses-pandas/deployment-3'
Creating flow run for deployment 'uses-pandas/deployment-3'...
Created flow run 'eccentric-caterpillar'.
└── UUID: b1e8875a-a358-4abc-9a4b-d9c1cc21dc6f
└── Parameters: {}
└── Job Variables: {}
└── Scheduled start time: 2025-05-28 16:18:33 CDT (now)
└── URL: http://127.0.0.1:4200/runs/flow-run/b1e8875a-a358-4abc-9a4b-d9c1cc21dc6f

» uv run --isolated prefect worker start --pool 'local' --run-once
Installed 134 packages in 239ms
Discovered type 'process' for work pool 'local'.
Worker 'ProcessWorker bae703d0-8d76-4078-b457-0e09c236f168' started!
16:18:46.965 | INFO    | prefect.flow_runs.worker - Worker 'ProcessWorker bae703d0-8d76-4078-b457-0e09c236f168' submitting flow run 'b1e8875a-a358-4abc-9a4b-d9c1cc21dc6f'
16:18:47.015 | INFO    | prefect.flow_runs.runner - Opening process...
16:18:47.037 | INFO    | prefect.flow_runs.worker - Completed submission of flow run 'b1e8875a-a358-4abc-9a4b-d9c1cc21dc6f'
16:18:47.612 | INFO    | Flow run 'eccentric-caterpillar' -  > Running git_clone step...
16:18:48.080 | INFO    | Flow run 'eccentric-caterpillar' -  > Running run_shell_script step...
Resolved 7 packages in 7ms
Installed 3 packages in 62ms
 + emoji==2.14.1
 + numpy==2.2.6
 + pandas==2.2.3
16:18:48.700 | INFO    | Flow run 'eccentric-caterpillar' - Beginning flow run 'eccentric-caterpillar' for flow 'uses-pandas'
16:18:48.700 | INFO    | Flow run 'eccentric-caterpillar' - View at http://127.0.0.1:4200/runs/flow-run/b1e8875a-a358-4abc-9a4b-d9c1cc21dc6f
16:18:55.115 | INFO    | Flow run 'eccentric-caterpillar' -    a  b
0  1  4
1  2  5
2  3  6
16:18:55.142 | INFO    | Flow run 'eccentric-caterpillar' - Finished in state Completed()
16:18:55.266 | INFO    | prefect.flow_runs.runner - Process for flow run 'eccentric-caterpillar' exited cleanly.
Worker 'ProcessWorker bae703d0-8d76-4078-b457-0e09c236f168' stopped!

» uv pip list | rg pandas

you should have full flexibility via uv with how you want to reuse or recreate a given virtual environment in a pull step

for example, you might want to define dependency-groups in your pyproject.toml and have each flow create a new venv like uv sync --group this-flow-group in your pull step

@PrefectHQ PrefectHQ locked and limited conversation to collaborators Jun 3, 2025
@zzstoatzz zzstoatzz converted this issue into discussion #18223 Jun 3, 2025

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
enhancement An improvement of an existing feature
Projects
None yet
Development

No branches or pull requests

2 participants
0