in src/Cli/func/Helpers/PythonHelpers.cs [211:277]
public static async Task<WorkerLanguageVersionInfo> GetEnvironmentPythonVersion()
{
// By circuiting here, we avoid computing the Python version multiple times
// in the scope of one command run
if (_pythonVersionCache != null)
{
return _pythonVersionCache;
}
// If users are overriding this value, we will use the path it's pointing to.
// This also allows for an escape path for complicated envrionments.
string pythonDefaultExecutablePath = Environment.GetEnvironmentVariable(_pythonDefaultExecutableVar);
if (!string.IsNullOrEmpty(pythonDefaultExecutablePath))
{
return await GetVersion(pythonDefaultExecutablePath);
}
// Windows Python Launcher (https://www.python.org/dev/peps/pep-0486/)
var pyGetVersionTask = PlatformHelper.IsWindows ? GetVersion("py") : Task.FromResult<WorkerLanguageVersionInfo>(null);
// Linux / OSX / Venv Interpreter Entrypoints
var python3GetVersionTask = GetVersion("python3");
var pythonGetVersionTask = GetVersion("python");
var python36GetVersionTask = GetVersion("python3.6");
var python37GetVersionTask = GetVersion("python3.7");
var python38GetVersionTask = GetVersion("python3.8");
var python39GetVersionTask = GetVersion("python3.9");
var python310GetVersionTask = GetVersion("python3.10");
var python311GetVersionTask = GetVersion("python3.11");
var python312GetVersionTask = GetVersion("python3.12");
var versions = new List<WorkerLanguageVersionInfo>
{
await pyGetVersionTask,
await python3GetVersionTask,
await pythonGetVersionTask,
await python36GetVersionTask,
await python37GetVersionTask,
await python38GetVersionTask,
await python39GetVersionTask,
await python310GetVersionTask,
await python311GetVersionTask,
await python312GetVersionTask
};
// Highest preference -- Go through the list, if we find the first python 3.6 or python 3.7 worker, we prioritize that.
WorkerLanguageVersionInfo recommendedPythonWorker = versions.FirstOrDefault(w => IsVersionSupported(w));
if (recommendedPythonWorker != null)
{
_pythonVersionCache = recommendedPythonWorker;
return _pythonVersionCache;
}
// If any of the possible python executables are 3.x, we will take that.
WorkerLanguageVersionInfo python3worker = versions.FirstOrDefault(w => w?.Major == 3);
if (python3worker != null)
{
_pythonVersionCache = python3worker;
return _pythonVersionCache;
}
// Least preferred -- If we found any python versions at all we return that
WorkerLanguageVersionInfo anyPythonWorker = versions.FirstOrDefault(w => !string.IsNullOrEmpty(w?.Version));
_pythonVersionCache = anyPythonWorker ?? new WorkerLanguageVersionInfo(WorkerRuntime.Python, null, null);
return _pythonVersionCache;
}