Last active
March 5, 2026 14:57
-
-
Save stevewithington/024fc85709d6c5a9e82dffcb9dee17a2 to your computer and use it in GitHub Desktop.
Installs pyenv-win, a couple versions of python, and sets the global version.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <# | |
| .SYNOPSIS | |
| Installs pyenv-win | |
| .DESCRIPTION | |
| Installs pyenv-win to $HOME\.pyenv | |
| If pyenv-win is already installed, try to update to the latest version. | |
| .PARAMETER Uninstall | |
| Uninstall pyenv-win. Note that this uninstalls any Python versions that were installed with pyenv-win. | |
| .PARAMETER Versions | |
| (Optional) A list of Python versions to install after pyenv-win is set up. Example usage: `.\install-pyenv-win.ps1 -Versions 3.12.10, 3.13.11, 3.14.2` | |
| Or, if you don't want to specify versions at install time, you can run `pyenv install <version>` after installation to install any version you want. | |
| Example: `./install-pyenv-win.ps1 -Versions ""` to skip installing versions at install time. | |
| .PARAMETER GlobalVersion | |
| (Optional) Set the global Python version after installation. Example usage: `.\install-pyenv-win.ps1 -Versions 3.12.10, 3.13.11, 3.14.2 -GlobalVersion 3.14.2` | |
| If not specified, the global version will not be set and will default to the system Python until you set it with `pyenv global <version>`. | |
| .EXAMPLE | |
| PS> install-pyenv-win.ps1 | |
| .LINK | |
| Original online version: https://pyenv-win.github.io/pyenv-win/ | |
| .NOTES | |
| To install or update pyenv-win, run this script in PowerShell. If you want to specify Python versions to install at the same time, use the -Versions parameter. | |
| Example: `.\install-pyenv-win.ps1 -Versions 3.12.10, 3.13.11, 3.14.2` | |
| To download this script, you can use the following command in PowerShell: | |
| `irm "https://gist.githubusercontent.com/stevewithington/024fc85709d6c5a9e82dffcb9dee17a2/raw/281589d755f3fb46658c4df52ba88b9fd3efa609/install-pyenv-win.ps1" -OutFile install-pyenv-win.ps1` | |
| To uninstall pyenv-win, run this script with the -Uninstall switch: `.\install-pyenv-win.ps1 -Uninstall` | |
| To run in memory without downloading the script, you can use the following command: | |
| `irm "https://gist.githubusercontent.com/stevewithington/024fc85709d6c5a9e82dffcb9dee17a2/raw/281589d755f3fb46658c4df52ba88b9fd3efa609/install-pyenv-win.ps1" | iex` | |
| #> | |
| param ( | |
| [Switch] $Uninstall, | |
| [String[]] $Versions = @('3.12.10', '3.13.11', '3.14.2'), | |
| [String] $GlobalVersion = '3.14.2' | |
| ) | |
| Set-StrictMode -Version Latest | |
| $ErrorActionPreference = 'Stop' | |
| $PyEnvDir = Join-Path $env:USERPROFILE '.pyenv' | |
| $PyEnvWinDir = Join-Path $PyEnvDir 'pyenv-win' | |
| $BinPath = Join-Path $PyEnvWinDir 'bin' | |
| $ShimsPath = Join-Path $PyEnvWinDir 'shims' | |
| $VersionUrl = 'https://raw.githubusercontent.com/pyenv-win/pyenv-win/master/.version' | |
| $ArchiveUrl = 'https://github.com/pyenv-win/pyenv-win/archive/master.zip' | |
| function Remove-PyEnvPaths { | |
| $PathParts = [System.Environment]::GetEnvironmentVariable('PATH', 'User') -split ';' | |
| $Cleaned = $PathParts.Where{ $_ -notin @($BinPath, $ShimsPath) } | |
| [System.Environment]::SetEnvironmentVariable('PATH', ($Cleaned -join ';'), 'User') | |
| } | |
| function Remove-PyEnvVars { | |
| Remove-PyEnvPaths | |
| foreach ($Var in 'PYENV', 'PYENV_ROOT', 'PYENV_HOME') { | |
| [System.Environment]::SetEnvironmentVariable($Var, $null, 'User') | |
| } | |
| } | |
| function Get-CurrentVersion { | |
| $VersionFile = Join-Path $PyEnvDir '.version' | |
| if (Test-Path $VersionFile) { return (Get-Content $VersionFile -Raw).Trim() } | |
| return $null | |
| } | |
| function Get-LatestVersion { | |
| return (Invoke-RestMethod -Uri $VersionUrl -UseBasicParsing).Trim() | |
| } | |
| function Install-PyEnv { | |
| $DownloadPath = Join-Path $PyEnvDir 'pyenv-win.zip' | |
| try { | |
| New-Item -Path $PyEnvDir -ItemType Directory -Force | Out-Null | |
| Invoke-WebRequest -Uri $ArchiveUrl -OutFile $DownloadPath -UseBasicParsing | |
| Expand-Archive -Path $DownloadPath -DestinationPath $PyEnvDir -Force | |
| $ExtractedDir = Join-Path $PyEnvDir 'pyenv-win-master' | |
| Get-ChildItem -Path $ExtractedDir | Move-Item -Destination $PyEnvDir -Force | |
| Remove-Item $ExtractedDir, $DownloadPath -Recurse -Force | |
| } | |
| catch { | |
| Write-Error "Download/extraction failed: $_" | |
| return $false | |
| } | |
| # Set environment variables | |
| $PyEnvWinTrailing = "$PyEnvWinDir\" | |
| foreach ($Var in 'PYENV', 'PYENV_ROOT', 'PYENV_HOME') { | |
| [System.Environment]::SetEnvironmentVariable($Var, $PyEnvWinTrailing, 'User') | |
| } | |
| # Update PATH — remove old entries first, then prepend | |
| $PathParts = [System.Environment]::GetEnvironmentVariable('PATH', 'User') -split ';' | |
| $Cleaned = $PathParts.Where{ $_ -notin @($BinPath, $ShimsPath) } | |
| $NewPath = (@($BinPath, $ShimsPath) + $Cleaned) -join ';' | |
| [System.Environment]::SetEnvironmentVariable('PATH', $NewPath, 'User') | |
| return $true | |
| } | |
| Function Install-Versions { | |
| foreach ($Version in $Versions) { | |
| Write-Host "Installing Python $Version..." -ForegroundColor Cyan | |
| & pyenv install $Version | |
| if ($LASTEXITCODE -ne 0) { | |
| Write-Host "Failed to install Python $Version. Please check the error message above and try installing manually with `pyenv install $Version`." -ForegroundColor Red | |
| } | |
| } | |
| } | |
| Function Set-GlobalVersion { | |
| if ($GlobalVersion) { | |
| Write-Host "Setting global Python version to $GlobalVersion..." -ForegroundColor Cyan | |
| & pyenv global $GlobalVersion | |
| if ($LASTEXITCODE -ne 0) { | |
| Write-Host "Failed to set global Python version to $GlobalVersion. Please check the error message above and try setting it manually with `pyenv global $GlobalVersion`." -ForegroundColor Red | |
| } else { | |
| Write-Host "Global Python version set to $GlobalVersion." -ForegroundColor Green | |
| $PythonVersion = & python --version | |
| if ($LASTEXITCODE -ne 0) { | |
| Write-Host "Failed to verify Python version after setting global version. Please ensure your terminal is restarted and try running `python --version`." -ForegroundColor Red | |
| } | |
| else { | |
| Write-Host "Current Python version: $PythonVersion" -ForegroundColor Green | |
| $SystemExe = python -c "import sys; print(sys.executable)" | |
| Write-Host "Python executable path: $SystemExe" -ForegroundColor Green | |
| } | |
| } | |
| } | |
| } | |
| # --- Main logic --- | |
| if ($Uninstall) { | |
| Write-Host 'Removing pyenv-win...' -ForegroundColor Yellow | |
| if (Test-Path $PyEnvDir) { Remove-Item -Path $PyEnvDir -Recurse -Force } | |
| Remove-PyEnvVars | |
| Write-Host 'pyenv-win successfully uninstalled.' -ForegroundColor Green | |
| exit 0 | |
| } | |
| $BackupDir = Join-Path $env:TEMP 'pyenv-win-backup' | |
| $FoldersToBackup = @('install_cache', 'versions', 'shims') | |
| $CurrentVersion = Get-CurrentVersion | |
| if ($CurrentVersion) { | |
| Write-Host "pyenv-win $CurrentVersion installed." -ForegroundColor Green | |
| $LatestVersion = Get-LatestVersion | |
| if ($CurrentVersion -eq $LatestVersion) { | |
| Write-Host 'No updates available.' | |
| exit 0 | |
| } | |
| Write-Host "New version available: $LatestVersion. Updating..." -ForegroundColor Cyan | |
| # Backup existing data in one pass | |
| New-Item -Path $BackupDir -ItemType Directory -Force | Out-Null | |
| foreach ($Dir in $FoldersToBackup) { | |
| $Source = Join-Path $PyEnvWinDir $Dir | |
| if (Test-Path $Source) { Move-Item -Path $Source -Destination $BackupDir } | |
| } | |
| Remove-Item -Path $PyEnvDir -Recurse -Force | |
| } | |
| if (Install-PyEnv) { | |
| # Restore backups if they exist | |
| if (Test-Path $BackupDir) { | |
| Write-Host 'Restoring Python installations...' -ForegroundColor Cyan | |
| Get-ChildItem -Path $BackupDir | Move-Item -Destination $PyEnvWinDir -Force | |
| Remove-Item -Path $BackupDir -Recurse -Force | |
| } | |
| Write-Host 'pyenv-win is successfully installed!' -ForegroundColor Green | |
| Write-Host 'Running `pyenv --version` to verify installation...' -ForegroundColor Cyan | |
| $pyenvVersion = & pyenv --version | |
| if ($LASTEXITCODE -ne 0) { | |
| Write-Host 'pyenv command failed to execute. Please ensure your terminal is restarted and try again.' -ForegroundColor Red | |
| exit 1 | |
| } | |
| else { | |
| Write-Host "$pyenvVersion" -ForegroundColor Green | |
| if ($Versions.Count -gt 0) { | |
| Install-Versions | |
| Set-GlobalVersion | |
| } | |
| } | |
| Write-Host 'Installation complete! Visit https://pyenv-win.github.io/pyenv-win/#usage for usage instructions.' -ForegroundColor Cyan | |
| } | |
| else { | |
| Write-Host 'pyenv-win was not installed successfully. If this issue persists, please open a ticket: https://github.com/pyenv-win/pyenv-win/issues.' -ForegroundColor Red | |
| exit 1 | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment