diff --git a/src/common/localize.ts b/src/common/localize.ts index e8d0aa6f..e6ce1f2f 100644 --- a/src/common/localize.ts +++ b/src/common/localize.ts @@ -15,6 +15,7 @@ export namespace Common { export const ok = l10n.t('Ok'); export const quickCreate = l10n.t('Quick Create'); export const installPython = l10n.t('Install Python'); + export const pythonNotFound = l10n.t('Python is not installed or not found in PATH. Please install Python to run Python files.'); } export namespace WorkbenchStrings { diff --git a/src/common/utils/executableExists.ts b/src/common/utils/executableExists.ts new file mode 100644 index 00000000..f5818438 --- /dev/null +++ b/src/common/utils/executableExists.ts @@ -0,0 +1,15 @@ +import which from 'which'; + +/** + * Checks if an executable exists in the system PATH. + * @param executable The name or path of the executable to check. + * @returns A promise that resolves to true if the executable exists, false otherwise. + */ +export async function executableExists(executable: string): Promise { + try { + await which(executable); + return true; + } catch (_err) { + return false; + } +} \ No newline at end of file diff --git a/src/features/execution/runInBackground.ts b/src/features/execution/runInBackground.ts index 39d0ce2c..5220d19b 100644 --- a/src/features/execution/runInBackground.ts +++ b/src/features/execution/runInBackground.ts @@ -1,5 +1,8 @@ import * as cp from 'child_process'; import { PythonEnvironment, PythonBackgroundRunOptions, PythonProcess } from '../../api'; +import { showErrorMessage } from '../../common/window.apis'; +import { executableExists } from '../../common/utils/executableExists'; +import { Common } from '../../common/localize'; export async function runInBackground( environment: PythonEnvironment, @@ -10,6 +13,12 @@ export async function runInBackground( const args = environment.execInfo?.activatedRun?.args ?? environment.execInfo?.run.args ?? []; const allArgs = [...args, ...options.args]; + // Check if the Python executable exists + if (!(await executableExists(executable))) { + await showErrorMessage(Common.pythonNotFound, { modal: true }, Common.installPython); + throw new Error(Common.pythonNotFound); + } + const proc = cp.spawn(executable, allArgs, { stdio: 'pipe', cwd: options.cwd, env: options.env }); return { diff --git a/src/features/terminal/runInTerminal.ts b/src/features/terminal/runInTerminal.ts index b650b9e3..1450441f 100644 --- a/src/features/terminal/runInTerminal.ts +++ b/src/features/terminal/runInTerminal.ts @@ -1,10 +1,12 @@ import { Terminal, TerminalShellExecution } from 'vscode'; import { PythonEnvironment, PythonTerminalExecutionOptions } from '../../api'; -import { onDidEndTerminalShellExecution } from '../../common/window.apis'; +import { onDidEndTerminalShellExecution, showErrorMessage } from '../../common/window.apis'; import { createDeferred } from '../../common/utils/deferred'; import { quoteArgs } from '../execution/execUtils'; import { identifyTerminalShell } from '../common/shellDetector'; import { ShellConstants } from '../common/shellConstants'; +import { executableExists } from '../../common/utils/executableExists'; +import { Common } from '../../common/localize'; export async function runInTerminal( environment: PythonEnvironment, @@ -20,6 +22,12 @@ export async function runInTerminal( const args = environment.execInfo?.activatedRun?.args ?? environment.execInfo?.run.args ?? []; const allArgs = [...args, ...(options.args ?? [])]; + // Check if the Python executable exists + if (!(await executableExists(executable))) { + await showErrorMessage(Common.pythonNotFound, { modal: true }, Common.installPython); + return; + } + if (terminal.shellIntegration) { let execution: TerminalShellExecution | undefined; const deferred = createDeferred();