FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

GitHub Viewer

using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.InteropServices; using Python.Runtime.Native; namespace Python.Runtime { /// /// This class provides the public interface of the Python runtime. /// public class PythonEngine : IDisposable { private static DelegateManager? delegateManager; private static bool initialized; private static IntPtr _pythonHome = IntPtr.Zero; private static IntPtr _programName = IntPtr.Zero; private static IntPtr _pythonPath = IntPtr.Zero; private static InteropConfiguration interopConfiguration = InteropConfiguration.MakeDefault(); public PythonEngine() { Initialize(); } public PythonEngine(params string[] args) { Initialize(args); } public PythonEngine(IEnumerable args) { Initialize(args); } public void Dispose() { Shutdown(); } public static bool IsInitialized { get { return initialized; } } private static void EnsureInitialized() { if (!IsInitialized) throw new InvalidOperationException( "Python must be initialized for this operation" ); } /// Set to true to enable GIL debugging assistance. public static bool DebugGIL { get; set; } = false; internal static DelegateManager DelegateManager { get { if (delegateManager == null) { throw new InvalidOperationException( "DelegateManager has not yet been initialized using Python.Runtime.PythonEngine.Initialize()."); } return delegateManager; } } public static InteropConfiguration InteropConfiguration { get => interopConfiguration; set { if (IsInitialized) throw new NotSupportedException("Changing interop configuration when engine is running is not supported"); interopConfiguration = value ?? throw new ArgumentNullException(nameof(InteropConfiguration)); } } public static string ProgramName { get { IntPtr p = Runtime.TryUsingDll(() => Runtime.Py_GetProgramName()); return UcsMarshaler.PtrToPy3UnicodePy2String(p) ?? ""; } set { Marshal.FreeHGlobal(_programName); _programName = Runtime.TryUsingDll( () => UcsMarshaler.Py3UnicodePy2StringtoPtr(value) ); Runtime.Py_SetProgramName(_programName); } } public static string PythonHome { get { EnsureInitialized(); IntPtr p = Runtime.TryUsingDll(() => Runtime.Py_GetPythonHome()); return UcsMarshaler.PtrToPy3UnicodePy2String(p) ?? ""; } set { // this value is null in the beginning Marshal.FreeHGlobal(_pythonHome); _pythonHome = UcsMarshaler.Py3UnicodePy2StringtoPtr(value); Runtime.TryUsingDll(() => Runtime.Py_SetPythonHome(_pythonHome)); } } public static string PythonPath { get { IntPtr p = Runtime.TryUsingDll(() => Runtime.Py_GetPath()); return UcsMarshaler.PtrToPy3UnicodePy2String(p) ?? ""; } set { Marshal.FreeHGlobal(_pythonPath); _pythonPath = Runtime.TryUsingDll( () => UcsMarshaler.Py3UnicodePy2StringtoPtr(value) ); Runtime.Py_SetPath(_pythonPath); } } public static Version MinSupportedVersion => new(3, 7); public static Version MaxSupportedVersion => new(3, 11, int.MaxValue, int.MaxValue); public static bool IsSupportedVersion(Version version) => version >= MinSupportedVersion && version = 0; --index) { if (ShutdownHandlers[index] == handler) { ShutdownHandlers.RemoveAt(index); break; } } } /// /// Run all the shutdown handlers. /// /// They're run in opposite order they were added. /// static void ExecuteShutdownHandlers() { while(ShutdownHandlers.Count > 0) { var handler = ShutdownHandlers[ShutdownHandlers.Count - 1]; ShutdownHandlers.RemoveAt(ShutdownHandlers.Count - 1); handler(); } } /// /// AcquireLock Method /// /// /// Acquire the Python global interpreter lock (GIL). Managed code /// *must* call this method before using any objects or calling any /// methods on objects in the Python.Runtime namespace. The only /// exception is PythonEngine.Initialize, which may be called without /// first calling AcquireLock. /// Each call to AcquireLock must be matched by a corresponding call /// to ReleaseLock, passing the token obtained from AcquireLock. /// For more information, see the "Extending and Embedding" section /// of the Python documentation on www.python.org. /// internal static PyGILState AcquireLock() { return Runtime.PyGILState_Ensure(); } /// /// ReleaseLock Method /// /// /// Release the Python global interpreter lock using a token obtained /// from a previous call to AcquireLock. /// For more information, see the "Extending and Embedding" section /// of the Python documentation on www.python.org. /// internal static void ReleaseLock(PyGILState gs) { Runtime.PyGILState_Release(gs); } /// /// BeginAllowThreads Method /// /// /// Release the Python global interpreter lock to allow other threads /// to run. This is equivalent to the Py_BEGIN_ALLOW_THREADS macro /// provided by the C Python API. /// For more information, see the "Extending and Embedding" section /// of the Python documentation on www.python.org. /// public static unsafe IntPtr BeginAllowThreads() { return (IntPtr)Runtime.PyEval_SaveThread(); } /// /// EndAllowThreads Method /// /// /// Re-aquire the Python global interpreter lock for the current /// thread. This is equivalent to the Py_END_ALLOW_THREADS macro /// provided by the C Python API. /// For more information, see the "Extending and Embedding" section /// of the Python documentation on www.python.org. /// public static unsafe void EndAllowThreads(IntPtr ts) { Runtime.PyEval_RestoreThread((PyThreadState*)ts); } public static PyObject Compile(string code, string filename = "", RunFlagType mode = RunFlagType.File) { var flag = (int)mode; NewReference ptr = Runtime.Py_CompileString(code, filename, flag); PythonException.ThrowIfIsNull(ptr); return ptr.MoveToPyObject(); } /// /// Eval Method /// /// /// Evaluate a Python expression and returns the result. /// It's a subset of Python eval function. /// public static PyObject Eval(string code, PyDict? globals = null, PyObject? locals = null) { PyObject result = RunString(code, globals.BorrowNullable(), locals.BorrowNullable(), RunFlagType.Eval); return result; } /// /// Exec Method /// /// /// Run a string containing Python code. /// It's a subset of Python exec function. /// public static void Exec(string code, PyDict? globals = null, PyObject? locals = null) { using PyObject result = RunString(code, globals.BorrowNullable(), locals.BorrowNullable(), RunFlagType.File); if (result.obj != Runtime.PyNone) { throw PythonException.ThrowLastAsClrException(); } } /// /// Exec Method /// /// /// Run a string containing Python code. /// It's a subset of Python exec function. /// internal static void Exec(string code, BorrowedReference globals, BorrowedReference locals = default) { using PyObject result = RunString(code, globals: globals, locals: locals, RunFlagType.File); if (result.obj != Runtime.PyNone) { throw PythonException.ThrowLastAsClrException(); } } /// /// Gets the Python thread ID. /// /// The Python thread ID. public static ulong GetPythonThreadID() { using PyObject threading = Py.Import("threading"); using PyObject id = threading.InvokeMethod("get_ident"); return id.As(); } /// /// Interrupts the execution of a thread. /// /// The Python thread ID. /// The number of thread states modified; this is normally one, but will be zero if the thread id is not found. public static int Interrupt(ulong pythonThreadID) { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { return Runtime.PyThreadState_SetAsyncExcLLP64((uint)pythonThreadID, Exceptions.KeyboardInterrupt); } return Runtime.PyThreadState_SetAsyncExcLP64(pythonThreadID, Exceptions.KeyboardInterrupt); } /// /// RunString Method. Function has been deprecated and will be removed. /// Use Exec/Eval/RunSimpleString instead. /// [Obsolete("RunString is deprecated and will be removed. Use Exec/Eval/RunSimpleString instead.")] public static PyObject RunString(string code, PyDict? globals = null, PyObject? locals = null) { return RunString(code, globals.BorrowNullable(), locals.BorrowNullable(), RunFlagType.File); } /// /// Internal RunString Method. /// /// /// Run a string containing Python code. Returns the result of /// executing the code string as a PyObject instance, or null if /// an exception was raised. /// internal static PyObject RunString(string code, BorrowedReference globals, BorrowedReference locals, RunFlagType flag) { if (code is null) throw new ArgumentNullException(nameof(code)); NewReference tempGlobals = default; if (globals.IsNull) { globals = Runtime.PyEval_GetGlobals(); if (globals.IsNull) { tempGlobals = Runtime.PyDict_New(); globals = tempGlobals.BorrowOrThrow(); Runtime.PyDict_SetItem( globals, PyIdentifier.__builtins__, Runtime.PyEval_GetBuiltins() ); } } if (locals == null) { locals = globals; } try { NewReference result = Runtime.PyRun_String( code, flag, globals, locals ); PythonException.ThrowIfIsNull(result); return result.MoveToPyObject(); } finally { tempGlobals.Dispose(); } } } public enum RunFlagType : int { Single = 256, File = 257, /* Py_file_input */ Eval = 258 } }

Back | FazBrowse Home | New Git URL