Auto-detect Python launcher on Windows
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
import { spawn } from "node:child_process";
|
||||||
import { constants as fsConstants } from "node:fs";
|
import { constants as fsConstants } from "node:fs";
|
||||||
import { access } from "node:fs/promises";
|
import { access } from "node:fs/promises";
|
||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
@@ -10,6 +11,23 @@ function splitCommand(command: string): string[] {
|
|||||||
return parts.map((part) => part.replace(/^"(.*)"$/, "$1"));
|
return parts.map((part) => part.replace(/^"(.*)"$/, "$1"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function canRun(command: string, args: string[]): Promise<boolean> {
|
||||||
|
return await new Promise<boolean>((resolve) => {
|
||||||
|
const child = spawn(command, [...args, "--version"], {
|
||||||
|
stdio: ["ignore", "ignore", "ignore"],
|
||||||
|
windowsHide: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
child.on("error", () => {
|
||||||
|
resolve(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
child.on("exit", (code) => {
|
||||||
|
resolve(code === 0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
async function fileExists(target: string): Promise<boolean> {
|
async function fileExists(target: string): Promise<boolean> {
|
||||||
try {
|
try {
|
||||||
await access(target, fsConstants.X_OK);
|
await access(target, fsConstants.X_OK);
|
||||||
@@ -39,10 +57,35 @@ export async function resolveBasePythonCommand(config: AppConfig): Promise<{ com
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (process.platform === "win32") {
|
if (process.platform === "win32") {
|
||||||
return { command: "python", args: [] };
|
const candidates = [
|
||||||
|
{ command: "python", args: [] as string[] },
|
||||||
|
{ command: "py", args: ["-3"] },
|
||||||
|
{ command: "py", args: [] as string[] },
|
||||||
|
];
|
||||||
|
|
||||||
|
for (const candidate of candidates) {
|
||||||
|
if (await canRun(candidate.command, candidate.args)) {
|
||||||
|
return candidate;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return { command: "python3", args: [] };
|
throw new Error(
|
||||||
|
"Windows에서 사용할 Python 실행기를 찾지 못했습니다. `python --version` 또는 `py -3 --version` 이 먼저 동작해야 합니다. 필요하면 .env 에 LOCAL_AI_PYTHON=python 또는 LOCAL_AI_PYTHON=py -3 를 넣으세요.",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const unixCandidates = [
|
||||||
|
{ command: "python3", args: [] as string[] },
|
||||||
|
{ command: "python", args: [] as string[] },
|
||||||
|
];
|
||||||
|
|
||||||
|
for (const candidate of unixCandidates) {
|
||||||
|
if (await canRun(candidate.command, candidate.args)) {
|
||||||
|
return candidate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error("사용 가능한 Python 실행기를 찾지 못했습니다. `python3 --version` 또는 `python --version` 이 먼저 동작해야 합니다.");
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function resolveWorkerPythonCommand(config: AppConfig): Promise<{ command: string; args: string[] }> {
|
export async function resolveWorkerPythonCommand(config: AppConfig): Promise<{ command: string; args: string[] }> {
|
||||||
|
|||||||
Reference in New Issue
Block a user