Public/Helper/Set-KrPythonRuntime.ps1
<# .SYNOPSIS Selects which CPython runtime pythonnet will embed. .DESCRIPTION • With no -Path the newest 64-bit CPython is auto-discovered. • If the env-var PYTHONNET_PYDLL is already present the function exits immediately—unless you pass -Force (or give an explicit -Path). • Applies the setting both to the environment and to the live [Python.Runtime.Runtime]::PythonDLL property when possible. .PARAMETER Path Full path to pythonXY.dll / libpythonX.Y.so / libpythonX.Y.dylib. .PARAMETER Force Override an existing PYTHONNET_PYDLL environment variable. .EXAMPLE # Leave current setting untouched if already configured Set-KrPythonRuntime .EXAMPLE # Override whatever is set and pin CPython 3.12 Set-KrPythonRuntime -Path '/opt/python312/lib/libpython3.12.so' -Force #> function Set-KrPythonRuntime { [KestrunRuntimeApi('Definition')] [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '')] [CmdletBinding()] param( [string] $Path, [switch] $Force ) # ------------------------------------------------------------ # 0. Does pythonnet already know a valid DLL / .so / .dylib? # ------------------------------------------------------------ $currentDll = [Python.Runtime.Runtime]::PythonDLL if (-not $Force -and -not $Path -and $currentDll -and (Test-Path $currentDll)) { Write-Verbose "pythonnet already configured → $currentDll" return (Resolve-Path $currentDll).Path } # ------------------------------------------------------------ # 1. If caller didn’t supply -Path, auto-discover # ------------------------------------------------------------ if (-not $Path) { if ($IsWindows) { # Windows: take the DLL next to the first python.exe on PATH $pyExe = (Get-Command python.exe, python3.exe -ErrorAction Ignore | Select-Object -First 1).Source if ($pyExe) { $Path = Get-ChildItem (Join-Path (Split-Path $pyExe) 'python*.dll') -ErrorAction Ignore | Sort-Object VersionInfo.FileVersion -Descending | Select-Object -First 1 -Expand FullName } } else { # Linux / macOS: ask whereis for libpython3*.so / .dylib $pattern = if ($IsMacOS) { 'libpython3*.dylib' } else { 'libpython3*.so' } $Path = & whereis -b $pattern 2>$null | Select-String -Pattern $pattern | ForEach-Object { $_.ToString().Split(' ', 2)[1] } | Sort-Object Length | Select-Object -First 1 } } if (-not $Path -or -not (Test-Path $Path)) { throw 'Could not locate a CPython runtime. Install Python ≥3.11 or supply -Path (-Force overrides existing setting).' } # ------------------------------------------------------------ # 2. Tell pythonnet to use this runtime # ------------------------------------------------------------ $Path = (Resolve-Path $Path).Path Write-Verbose "pythonnet will use: $Path" # If pythonnet already loaded: update in-process [Python.Runtime.Runtime]::PythonDLL = $Path return $Path } |