Repository navigation
Expand file tree
/
Copy pathPythonInitializer.cs
More file actions
140 lines (123 loc) · 5.22 KB
/
Copy pathPythonInitializer.cs
File metadata and controls
140 lines (123 loc) · 5.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
// Copyright 2012-2022 Keysight Technologies
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
using Python.Runtime;
using System;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
namespace OpenTap.Python
{
static class PythonInitializer
{
const string loadScript = @"import sys
def add_dir(x):
sys.path.insert(0, x)
";
static readonly TraceSource log = Log.CreateSource("Python");
static bool initialized;
static bool initSuccess;
static readonly object loadLock = new object();
public static bool LoadPython(bool reinit = false)
{
lock (loadLock)
{
if (initialized && !reinit) return initSuccess;
initialized = true;
if (!InitInternal())
return false;
initSuccess = true;
return true;
}
}
/// <summary>
/// init_internal refers to Python.Runtime, but to find this we need to help the assembly resolver by adding site-packages to DirectoriesToSearch.
/// </summary>
[MethodImpl(MethodImplOptions.NoInlining)]
static bool InitInternal()
{
if (!PythonEngine.IsInitialized)
{
try
{
var installations = PythonDiscoverer.Instance.GetAvailablePythonInstallations()
.ToArray();
if (!installations.Any())
{
log.Warning("No Python installations found.");
return false;
}
var (pyLoc, pyPath) = installations.First();
if (File.Exists(pyLoc) == false)
{
log.Warning($"Unable to load Python: File does not exist " + pyLoc);
return false;
}
Runtime.PythonDLL = pyLoc;
// In some cases the python home is not known.
// if som try to get it from pyPath.
// only done on windows, because it is less ambiguous on Linux when
// python is installed with a package.
if(pyPath != null && SharedLib.IsWin32)
PythonEngine.PythonHome = pyPath;
PythonEngine.ProgramName = Assembly.GetEntryAssembly().Location;
var venv = PythonSettings.Current.VirtualEnvironment;
if (string.IsNullOrWhiteSpace(venv) == false)
{
var pypath2 = $"{venv}\\Lib\\site-packages\\;{venv}\\LIB";
Environment.SetEnvironmentVariable("PYTHONPATH", pypath2);
}
PythonEngine.Initialize(false);
log.Debug("PYTHONPATH: " + Environment.GetEnvironmentVariable("PYTHONPATH"));
log.Debug("PYTHONHOME: " + Environment.GetEnvironmentVariable("PYTHONHOME"));
log.Debug($"PythonEngine.PythonPath: {PythonEngine.PythonPath}");
log.Debug($"PythonEngine.PythonPath: {PythonEngine.PythonHome}");
PythonEngine.BeginAllowThreads();
log.Debug($"Loaded Python Version {PythonEngine.Version} from '{pyPath}'.");
}
catch (Exception ex)
{
log.Error("Unable to load python: " + ex.Message);
log.Debug(ex);
return false;
}
if (!PythonEngine.IsInitialized)
return false;
using (Py.GIL())
{
PyObject mod = PyModule.FromString("init_mod", loadScript);
foreach (var s in PythonSettings.Current.GetSearchList())
mod.InvokeMethod("add_dir", s.ToPython());
try
{
Py.Import("opentap");
}
catch (PythonException e)
{
PrintPythonException(e);
log.Error("Unable to initialize OpenTAP.");
return false;
}
}
}
return true;
}
static void PrintPythonException(PythonException pyx)
{
log.Error(pyx.Message);
var trace = pyx.StackTrace;
if (trace.Contains(']'))
trace = trace.Substring(0, trace.IndexOf(']'));
var stk = trace.Split(new string[] {"\\n"}, StringSplitOptions.RemoveEmptyEntries).Reverse();
foreach (var line in stk)
{
var cleaned = line.Replace("[", "").Replace("]", "").Replace("'", "").Trim();
cleaned = cleaned.TrimStart(',').Trim();
log.Info(cleaned);
}
}
}
}