uvtrick

repository·main·Indexed 42 days ago

https://github.com/koaning/uvtrick

A tool that uses uv and pickle to run Python code in separate virtual environments and return results to the caller. It provides the Env class for executing functions with specific dependencies and Python versions, and a load() function to execute functions from external scripts using inline script metadata.

Tokens
1.4K
Snippets
5
Records
5
Agent score
3%

What's inside uvtrick

  1. Run functions in specific environments using Env

    main

    The Env class allows you to run a Python function within a specific, isolated environment defined by dependencies and a Python version. This is particularly useful for testing code against different versions of a dependency (e.g., to check for performance regressions or compatibility).

    Usage Pattern:

    1. Define the function you want to run.
    2. Instantiate Env with the required package(s) and optional python version.
    3. Call .run() passing the function and any necessary arguments.

    Warning: Because communication happens via pickle, ensure the function returns base Python objects and that the calling environment can handle the returned data.

    from uvtrick import Env
    
    def uses_rich(a, b):
        from rich import print
        from importlib import metadata
    
        version = metadata.version("rich")
        print(f"hello from rich=={version}")
        return a + b
    
    # Run the function in an environment with specific versions of 'rich'
    for version in (10, 11, 12, 13):
        Env(f"rich=={version}", python="3.12").run(uses_rich, a=1, b=2)
  2. Run a function from an external script using load()

    main

    Use the load function to execute a specific function located in an external Python script. This function requires the target script to include inline script metadata.

    Important Limitations:

    • The function runs in a separate virtual environment managed by uv.
    • Results are communicated back to your current environment via pickle.
    • Only use base Python objects for inputs and return values to avoid pickling errors.
    • Avoid passing large objects or objects that require dependencies not present in your current environment.
    from uvtrick import load
    
    # Load the function `add` from the file `some_script.py`
    add = load("some_script.py", "add")
    
    # The function runs in another venv, but returns the result via pickle
    result = add(1, 2)  # 3
  3. Manage isolated execution environments with `Env`

    main

    The Env class provides a way to define and run functions within a specific virtual environment with controlled Python versions and dependencies using uv.

    Initialization Parameters:

    • *requirements: A variable number of strings representing package dependencies (e.g., Env("requests", "pandas")).
    • python: (Optional) A string specifying the Python version to use (e.g., "3.11").
    • debug: (Optional) A boolean. If True, the environment will log execution details to STDOUT via the report() method.

    Key Methods:

    • run(func, *args, **kwargs): Executes the provided function in the managed environment. It serializes arguments using cloudpickle, runs the script via uv run, and deserializes the result.
    • report(contents): If debug is enabled, this logs the temporary directory, the command being run, the pickled arguments, and the generated script content.
    from uvtrick import Env
    
    def my_function(x, y):
        return x + y
    
    # Create an environment with specific dependencies
    env = Env("numpy", python="3.10", debug=True)
    
    # Run the function in that environment
    result = env.run(my_function, 10, y=20)
    print(result)  # 30
  4. Load and execute functions from external files with `load()`

    main

    The load(path, func) function allows you to execute a specific function from a Python file within a separate virtual environment managed by uv.

    Requirements:

    • The target Python file must use inline script metadata (e.g., # /// script blocks) to declare its dependencies.
    • The function being called should ideally return base Python objects, as communication between environments is handled via cloudpickle.

    load returns a wrapper function that, when called, triggers the execution in the external environment.

    from uvtrick import load
    
    # Load the function `hello` from the file `some_script.py`
    # It runs in another virtualenv, but you get back the response via cloudpickle.
    # Be aware of the limitations, please only consider base Python objects.
    hello = load("some_script.py", "hello")
    
    # Call the returned function
    result = hello(arg1, key="value")