This class makes it simpler.
Examples.
// class "Pynet.cs"
/*/ nuget PyNet\PythonNet; /*/
using Python.Runtime;
/// <summary>
/// Initializes the Python engine, locks its global interpreter and adds scope.
/// Optionally adds Python code; then you can call functions etc.
/// When disposing, unlocks/disposes objects and shuts down the engine.
/// </summary>
public class Pynet : IDisposable {
Py.GILState _gil;
PyModule _m;
bool _shutdown;
/// <summary>
/// Initializes the Python engine and optionally adds code.
/// </summary>
/// <param name="code">If not null/"", calls <b>PyModule.Exec</b>.</param>
/// <param name="enablePrint">Redirect the output of the Python's print function to console. Default true.</param>
public Pynet(string code = null, bool enablePrint = true) {
if (!PythonEngine.IsInitialized) {
if (Environment.GetEnvironmentVariable("PYTHONNET_PYDLL").NE()) Runtime.PythonDLL = @"C:\Program Files\Python311\python311.dll"; //edit this if need. Or set the environment variable.
PythonEngine.Initialize();
_shutdown = true;
//process.thisProcessExit += _ => PythonEngine.Shutdown(); //does not work
}
_gil = Py.GIL();
if (enablePrint) {
Module.Exec("""
import sys
class NetConsole(object):
def __init__(self, writeCallback):
self.writeCallback = writeCallback
def write(self, message):
self.writeCallback(message)
def flush(self):
pass
def setConsoleOut(writeCallback):
sys.stdout = NetConsole(writeCallback)
""");
var writer = (string s) => { Console.Write(s); };
Module.InvokeMethod("setConsoleOut", Python.Runtime.PyObject.FromManagedObject(writer));
}
if (!code.NE()) Module.Exec(code);
}
/// <summary>
/// Unlocks/disposes Python objects and shuts down the engine.
/// </summary>
public void Dispose() {
_m?.Dispose();
_gil?.Dispose();
if (_shutdown) {
try { PythonEngine.Shutdown(); } //without this the process does not exit
catch (System.Runtime.Serialization.SerializationException) { } //thrown when using enablePrint
}
}
/// <summary>
/// Gets the result of <b>Py.CreateScope</b>.
/// You can assign it to a <c>dynamic</c> variable and call functions defined in your Python code.
/// </summary>
public PyModule Module => _m ??= Py.CreateScope();
}
Examples.
// script "Pynet examples.cs"
/*/ c Pynet.cs; /*/
using Python.Runtime;
#if true
string code = """
def Multi(a1, a2):
return a1 * a2
def JoinStr(a1, a2):
return a1 + a2
""";
using var pyn = new Pynet(code);
dynamic m = pyn.Module;
double d1 = m.Multi(2, 3.5);
string s1 = m.JoinStr("joi", "ned");
print.it(d1, s1);
#elif !true
using var pyn = new Pynet();
dynamic mod = Py.Import("math");
print.it(mod.cos(mod.pi * 2));
#elif !true
using var pyn = new Pynet();
print.it(PythonEngine.Eval("3 + 4"));
#elif !true
string code = """
import ctypes
ctypes.windll.user32.MessageBoxW(0, "Text", "Title", 1)
""";
using var pyn = new Pynet();
PythonEngine.RunSimpleString(code);
#endif