fix: auto-install python3-venv when ensurepip is missing on Linux

On Ubuntu/Debian, python3 is often pre-installed but python3-venv is
not, causing venv creation to fail with "ensurepip is not available".
Now detects this error and auto-installs the matching python3.x-venv
package via apt-get before retrying.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
jim800121chen 2026-03-25 00:10:53 +08:00
parent 75885c5691
commit 1a2811f8c9
4 changed files with 53 additions and 1 deletions

View File

@ -424,7 +424,24 @@ func (inst *Installer) setupPythonVenv(installDir string) error {
cmd := exec.Command(pythonPath, "-m", "venv", venvDir)
if out, err := cmd.CombinedOutput(); err != nil {
return fmt.Errorf("venv creation failed: %s — %w", string(out), err)
// On Linux, ensurepip may be missing — install python3-venv and retry
if runtime.GOOS == "linux" && strings.Contains(string(out), "ensurepip") {
inst.emitProgress(ProgressEvent{
Step: "python",
Message: "Installing python3-venv package...",
Percent: 77,
})
if installErr := inst.installPython3Venv(pythonPath); installErr != nil {
return fmt.Errorf("venv creation failed and python3-venv install failed: %w", installErr)
}
// Retry venv creation
cmd = exec.Command(pythonPath, "-m", "venv", venvDir)
if out2, err2 := cmd.CombinedOutput(); err2 != nil {
return fmt.Errorf("venv creation still failed after installing python3-venv: %s — %w", string(out2), err2)
}
} else {
return fmt.Errorf("venv creation failed: %s — %w", string(out), err)
}
}
inst.emitProgress(ProgressEvent{

View File

@ -73,6 +73,11 @@ func (inst *Installer) autoInstallPython3() error {
return nil
}
// installPython3Venv is a no-op on macOS (venv is bundled with Python).
func (inst *Installer) installPython3Venv(pythonPath string) error {
return fmt.Errorf("python3-venv not available — please reinstall Python 3")
}
func installLibusb(installDir string) error {
if _, err := exec.LookPath("brew"); err != nil {
return fmt.Errorf("Homebrew not found. Install from https://brew.sh then retry")

View File

@ -136,6 +136,31 @@ func (inst *Installer) autoInstallPython3() error {
return nil
}
// installPython3Venv installs the python3-venv package matching the Python version.
func (inst *Installer) installPython3Venv(pythonPath string) error {
if _, err := exec.LookPath("apt-get"); err != nil {
return fmt.Errorf("apt-get not found — please install python3-venv manually")
}
// Detect Python minor version to install the matching venv package
// e.g. python3.12 -> python3.12-venv
out, err := exec.Command(pythonPath, "-c", "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')").Output()
if err != nil {
// Fallback to generic package
cmd := exec.Command("pkexec", "apt-get", "install", "-y", "python3-venv")
return cmd.Run()
}
ver := strings.TrimSpace(string(out))
pkg := fmt.Sprintf("python%s-venv", ver)
cmd := exec.Command("pkexec", "apt-get", "install", "-y", pkg)
if out, err := cmd.CombinedOutput(); err != nil {
return fmt.Errorf("apt-get install %s failed: %s — %w", pkg, string(out), err)
}
return nil
}
func installFfmpeg(inst *Installer, needFfmpeg, needYtdlp bool) error {
if _, err := exec.LookPath("apt-get"); err != nil {
return fmt.Errorf("package manager not found — please install ffmpeg manually")

View File

@ -114,6 +114,11 @@ func (inst *Installer) autoInstallPython3() error {
return nil
}
// installPython3Venv is a no-op on Windows (venv is bundled with Python).
func (inst *Installer) installPython3Venv(pythonPath string) error {
return fmt.Errorf("python3-venv not available — please reinstall Python 3")
}
func installLibusb(installDir string) error {
// 1. Extract libusb-1.0.dll from payload
dllDest := filepath.Join(installDir, "libusb-1.0.dll")