| | 1 | | <# |
| | 2 | | .SYNOPSIS |
| | 3 | | Selects which CPython runtime pythonnet will embed. |
| | 4 | |
|
| | 5 | | .DESCRIPTION |
| | 6 | | • With no -Path the newest 64-bit CPython is auto-discovered. |
| | 7 | | • If the env-var PYTHONNET_PYDLL is already present the function |
| | 8 | | exits immediately—unless you pass -Force (or give an explicit -Path). |
| | 9 | | • Applies the setting both to the environment and to the live |
| | 10 | | [Python.Runtime.Runtime]::PythonDLL property when possible. |
| | 11 | |
|
| | 12 | | .PARAMETER Path |
| | 13 | | Full path to pythonXY.dll / libpythonX.Y.so / libpythonX.Y.dylib. |
| | 14 | |
|
| | 15 | | .PARAMETER Force |
| | 16 | | Override an existing PYTHONNET_PYDLL environment variable. |
| | 17 | |
|
| | 18 | | .EXAMPLE |
| | 19 | | # Leave current setting untouched if already configured |
| | 20 | | Set-KrPythonRuntime |
| | 21 | |
|
| | 22 | | .EXAMPLE |
| | 23 | | # Override whatever is set and pin CPython 3.12 |
| | 24 | | Set-KrPythonRuntime -Path '/opt/python312/lib/libpython3.12.so' -Force |
| | 25 | | #> |
| | 26 | | function Set-KrPythonRuntime { |
| | 27 | | [KestrunRuntimeApi('Definition')] |
| | 28 | | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '')] |
| | 29 | | [CmdletBinding()] |
| | 30 | | param( |
| | 31 | | [string] $Path, |
| | 32 | | [switch] $Force |
| | 33 | | ) |
| | 34 | |
|
| | 35 | | # ------------------------------------------------------------ |
| | 36 | | # 0. Does pythonnet already know a valid DLL / .so / .dylib? |
| | 37 | | # ------------------------------------------------------------ |
| 0 | 38 | | $currentDll = [Python.Runtime.Runtime]::PythonDLL |
| | 39 | |
|
| 0 | 40 | | if (-not $Force -and -not $Path -and |
| 0 | 41 | | $currentDll -and (Test-Path $currentDll)) { |
| | 42 | |
|
| 0 | 43 | | Write-Verbose "pythonnet already configured → $currentDll" |
| 0 | 44 | | return (Resolve-Path $currentDll).Path |
| | 45 | | } |
| | 46 | |
|
| | 47 | | # ------------------------------------------------------------ |
| | 48 | | # 1. If caller didn’t supply -Path, auto-discover |
| | 49 | | # ------------------------------------------------------------ |
| 0 | 50 | | if (-not $Path) { |
| 0 | 51 | | if ($IsWindows) { |
| | 52 | | # Windows: take the DLL next to the first python.exe on PATH |
| 0 | 53 | | $pyExe = (Get-Command python.exe, python3.exe -ErrorAction Ignore | |
| 0 | 54 | | Select-Object -First 1).Source |
| 0 | 55 | | if ($pyExe) { |
| 0 | 56 | | $Path = Get-ChildItem (Join-Path (Split-Path $pyExe) 'python*.dll') -ErrorAction Ignore | |
| 0 | 57 | | Sort-Object VersionInfo.FileVersion -Descending | |
| 0 | 58 | | Select-Object -First 1 -Expand FullName |
| | 59 | | } |
| | 60 | | } else { |
| | 61 | | # Linux / macOS: ask whereis for libpython3*.so / .dylib |
| 0 | 62 | | $pattern = if ($IsMacOS) { 'libpython3*.dylib' } else { 'libpython3*.so' } |
| 0 | 63 | | $Path = & whereis -b $pattern 2>$null | |
| 0 | 64 | | Select-String -Pattern $pattern | |
| 0 | 65 | | ForEach-Object { $_.ToString().Split(' ', 2)[1] } | |
| 0 | 66 | | Sort-Object Length | Select-Object -First 1 |
| | 67 | | } |
| | 68 | | } |
| | 69 | |
|
| 0 | 70 | | if (-not $Path -or -not (Test-Path $Path)) { |
| 0 | 71 | | throw 'Could not locate a CPython runtime. Install Python ≥3.11 or supply -Path (-Force overrides existing setti |
| | 72 | | } |
| | 73 | |
|
| | 74 | | # ------------------------------------------------------------ |
| | 75 | | # 2. Tell pythonnet to use this runtime |
| | 76 | | # ------------------------------------------------------------ |
| 0 | 77 | | $Path = (Resolve-Path $Path).Path |
| 0 | 78 | | Write-Verbose "pythonnet will use: $Path" |
| | 79 | | # If pythonnet already loaded: update in-process |
| 0 | 80 | | [Python.Runtime.Runtime]::PythonDLL = $Path |
| | 81 | |
|
| 0 | 82 | | return $Path |
| | 83 | | } |
| | 84 | |
|