Python Environment APIs
Pages 34
-
- Functions
- Events
- onDidChangeEnvironments
- onDidChangeActiveEnvironmentPath
- Interfaces
- EnvPathType
- EnvironmentsChangeEvent
- ActiveEnvironmentPathChangeEvent
- RefreshOptions
- Extension API Usage
- Get the python extension api
- Get the active environment to run some script
- Change the current active environment
- Get notified when active environment is changed
- Get current known environments regardless of refresh state
- Detect new environments or changes to the interpreters list
- Get all details for a particular environment
- Get all details for all environments in the machine
- Look for a particular environment and set it
- Icebox following requests
- Allow to register a provider
- Request for API on how to run environments
- Request for getEnvironmentVariables and onDidChangeGetEnvironmentVariables
Clone this wiki locally
These APIs provide a way for extensions to work with by python environments available in the user's machine as found by the Python extension.
Functions
-
getActiveEnvironmentPath(resource?: Resource): EnvironmentPath;
Returns the path to the python binary selected by the user or as in the settings. This is just the path to the python binary, this does not provide activation or any other activation command. The
resourceif provided will be used to determine the python binary in a multi-root scenario. If resource isundefinedthen the API returns what ever is set for the workspace.Params:
-
resource: Uri of a file or workspace folder. This is used to determine the env in a multi-root scenario. Ifundefined, then the API returns what ever is set for the workspace.
-
-
updateActiveEnvironmentPath( environment: string | EnvironmentPath | Environment, resource?: Resource, ): Promise<void>;
Sets the active environment path for the python extension for the resource. Configuration target will always be the workspace folder.
Params:
-
environment: Full path to environment folder or python executable for the environment. Can also pass the environment itself. -
resource: [optional] File or workspace to scope to a particular workspace folder.
-
-
readonly known: Environment[];
Carries environments known to the extension at the time of fetching the property. Note this may not contain all environments in the system as a refresh might be going on.
-
resolveEnvironment( environment: Environment | EnvironmentPath | string, ): Promise<ResolvedEnvironment | undefined>;
Returns details for the given environment, or
undefinedif the env is invalid.Params:
- environment: Full path to environment folder or python executable for the environment. Can also pass the environment id or the environment itself.
-
refreshEnvironments(options?: RefreshOptions, token?: CancellationToken): Promise<void>;
This API will trigger environment discovery, but only if it has not already happened in this VSCode session. Useful for making sure env list is up-to-date when the caller needs it for the first time.
To force trigger a refresh regardless of whether a refresh was already triggered, see option
RefreshOptions.forceRefresh.Params:
- options:
RefreshOptions- forceRefresh: When
true, force trigger a refresh regardless of whether a refresh was already triggered. Note this can be expensive so it's best to only use it if user manually triggers a refresh.
- forceRefresh: When
- options:
Events
onDidChangeEnvironments
This event is triggered when the known environment list changes, like when a environment is found, existing environment is removed, or some details changed on an environment.
Events:
- "add": New environment is added.
- "remove": Existing environment in the list is removed.
- "update": New information found about existing environment.
This event addresses the API request from Jupyter extension https://github.com/microsoft/vscode-python/issues/17004
Event Type: EnvironmentsChangeEvent
onDidChangeActiveEnvironmentPath
Event triggered when either user selects an interpreter or updateActiveEnvironmentPath results in a change.
Event Type: ActiveEnvironmentPathChangeEvent
Interfaces
EnvPathType
export type EnvironmentPath = {
readonly id: string;
/**
* Path to environment folder or path to python executable that uniquely identifies an environment. Environments
* lacking a python executable are identified by environment folder paths, whereas other envs can be identified
* using python executable path.
*/
readonly path: string;
};EnvironmentsChangeEvent
export type EnvironmentsChangeEvent = {
readonly env: Environment;
readonly type: 'add' | 'remove' | 'update';
};ActiveEnvironmentPathChangeEvent
export type ActiveEnvironmentPathChangeEvent = EnvironmentPath & {
/**
* Workspace folder the environment changed for.
*/
readonly resource: WorkspaceFolder | undefined;
};RefreshOptions
export type RefreshOptions = {
/**
* When `true`, force trigger a refresh regardless of whether a refresh was already triggered. Note this can be expensive so
* it's best to only use it if user manually triggers a refresh.
*/
forceRefresh?: boolean;
};Extension API Usage
Get the python extension api
Copy over contents of https://github.com/microsoft/vscode-python/blob/main/src/client/apiTypes.ts as needed.
const extension = extensions.getExtension('ms-python.python');
if (extension) {
if (!extension.isActive) {
await extension.activate();
}
const pythonApi: IExtensionAPI = extension.exports as IExtensionAPI;
}Get the active environment to run some script
// This will return something like /usr/bin/python
const environmentPath = pythonApi.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 pythonApi.environments.resolveEnvironment(environmentPath);
if (environment) {
// run your script here.
}Change the current active environment
await pythonApi.environments.updateActiveEnvironment('/bin/usr/python');Get notified when active environment is changed
let currentActivePython = undefined;
extContext.subscriptions.push(
pythonApi.environments.onDidChangeActiveEnvironment((e: ActiveEnvironmentPathChangeEvent) => {
currentActivePython = e.path;
}),
);
// Get currently selected environment.
currentActivePython = pythonApi.environments.getActiveEnvironmentPath()?.path;Get current known environments regardless of refresh state
// Use this way if you don't really want to wait for the extension to fully load info for all environments.
const environments = pythonApi.environments.known;Detect new environments or changes to the interpreters list
const environments: string[] | undefined;
extContext.subscriptions.push(
pythonApi.environments.onDidEnvironmentsChanged((e: EnvironmentsChangeEvent) => {
if (environments) {
// handle changes here based on add, remove, update
}
}),
);
// Get the current list of environments.
environments = pythonApi.environments.known;Get all details for a particular environment
const detail = pythonApi.environments.resolveEnvironment(`usr/bin/python`);Get all details for all environments in the machine
// Trigger a full refresh and wait for it to complete.
await pythonApi.environments.refreshEnvironments();
const environments = pythonApi.environments.known;Look for a particular environment and set it
const envs = pythonApi.environments.known;
const foundEnv = envs.find(p => p.name === 'envName');
if (foundEnv) {
await pythonApi.environments.updateActiveEnvironment(foundEnv);
} else {
// Could not find the path, maybe a refresh is needed?
await pythonApi.environments.refreshEnvironments();
const foundEnv = envs.find(p => p.name === 'envName');
if (foundEnv) {
await pythonApi.environments.updateActiveEnvironment(foundEnv);
} else {
// Environment not found in the system.
}
}Icebox following requests
Allow to register a provider
registerEnvironmentProvider(
environmentProvider: IEnvironmentProvider,
metadata: EnvironmentProviderMetadata,
): Promise<Disposable>;
// TODO: Figure out whether to return a promise or notRequest for API on how to run 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 getEnvironmentVariables 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.