Skip to content

Python Environment APIs

Kartik Raj edited this page Feb 29, 2024 · 11 revisions

These APIs provide a way for extensions to work with Python environments available in the user's machine as found by the Python extension.

Get the Python extension API

@vscode/python-extension npm module carries types and helper utilities to access the feature. Follow instructions there to add Python extension and module as a dependency to your extension first. Then,

// Import the API
import { PythonExtension } from '@vscode/python-extension';

...

// Load the Python extension API
const pythonApi: PythonExtension = await PythonExtension.api();
const environments = pythonApi.environments;

Extension API Usage

Get the active environment to run some script

// This will return something like /usr/bin/python
const environmentPath = environments.getActiveEnvironmentPath();

// `environmentPath.path` carries the value of the setting. Note that this path may point to a folder and not the
// python binary. Depends entirely on how the env was created.
// E.g., `conda create -n myenv python` ensures the env has a python binary
// `conda create -n myenv` does not include a python binary.
// Also, the path specified may not be valid, use the following to get complete details for this environment if
// need be.

const environment = await environments.resolveEnvironment(environmentPath);
if (environment) {
    // run your script here.
}

Change the current active environment

await environments.updateActiveEnvironment('/bin/usr/python');

Get notified when active environment is changed

let currentActivePython = undefined;
extContext.subscriptions.push(
    environments.onDidChangeActiveEnvironment((e: ActiveEnvironmentPathChangeEvent) => {
        currentActivePython = e.path;
    }),
);
// Get currently selected environment.
currentActivePython = environments.getActiveEnvironmentPath()?.path;

Get current known environments

// Use this way if you don't really want to wait for the extension to fully load info for all environments.
const environments = environments.known;

Detect new environments or changes to the interpreters discovered in the system

const environments: string[] | undefined;
extContext.subscriptions.push(
    environments.onDidEnvironmentsChanged((e: EnvironmentsChangeEvent) => {
        if (environments) {
            // handle changes here based on add, remove, update
        }
    }),
);

// Get the current list of environments.
environments = environments.known;

Get all details for a particular environment

const detail = environments.resolveEnvironment(`usr/bin/python`);

Get all details for all environments in the system

// Trigger a full refresh and wait for it to complete.
await environments.refreshEnvironments();
const environments = environments.known;

Look for a particular environment and set it

const envs = environments.known;
const foundEnv = envs.find(p => p.name === 'envName');
if (foundEnv) {
    await environments.updateActiveEnvironment(foundEnv);
} else {
    // Could not find the path, maybe a refresh is needed?
    await environments.refreshEnvironments();
    const foundEnv = envs.find(p => p.name === 'envName');
    if (foundEnv) {
        await environments.updateActiveEnvironment(foundEnv);
    } else {
        // Environment not found in the system.
    }
}

Upcoming potential APIs

Allow to register a provider

registerEnvironmentProvider(
    environmentProvider: IEnvironmentProvider,
    metadata: EnvironmentProviderMetadata,
): Disposable;

Allow execution in environments

run: {
    // Functions would only require the arguments. The env provider can internally decide on the commands.
    exec: Function;
    shellExec: Function; // Only for backwards compatibility.
    execObservable: Function;
    /**
     * Uses a VSCode terminal.
     * */
    terminalExec: () => void;
    /**
     * Any environment variables that can be used to activate the environment, if supported.
     * If not provided, Python extension itself uses the other execution APIs to calculate it.
     */
    env?: { [key: string]: string | null | undefined };
};

Request for getActivatedEnvironmentVariables and onDidChangeGetEnvironmentVariables

https://github.com/microsoft/vscode-python/issues/15112 This can be problematic, although the request asks for PYTHONPATH, in a activated environment scenario we will have to provide activated environment variables, and somehow also detect environment variable changes when new packages are introduced to the environment which can make those environment changes. At this point we provide the detail about the environment type, it is up to the consumer to get the variables as they are needed.

We could revisit this when we have better activation story for ourselves.

Clone this wiki locally