Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Execute Python Code in QM Using python.net
#17
It may be necessary to upgrade csc.exe, as the system's default C# 5 cannot execute the following code.

demo:
https://i.ibb.co/chzkdkg3/pycall.gif

Function Pynet2
Code:
Copy      Help
out

CsScript x
str Opt=
;searchDirs=$qm$
;references=System.Core;Python.Runtime.dll;Microsoft.CSharp;netstandard
;compilerOptions=/warn:1
x.SetOptions(Opt 1)

x.AddCode("")
str code=
;###pywin32
;import ctypes
;print("hello world from python!")
;
;import win32print
;print(win32print.__file__)
;
;default_printer = win32print.GetDefaultPrinter()
;print(default_printer)

x.Call("Pynet.pyCall" code)


#ret
using System;
using System.IO;
using System.Diagnostics;
using System.Reflection;
using System.Linq;
using Python.Runtime;
using System.Collections;
using System.Collections.Generic;

public class Pynet : IDisposable
{
,Py.GILState _gil;
,PyModule _m;
,bool _shutdown;

,public static object pyCall(string code)
,{
,,,using (var pyn = new Pynet())
,,,{
,,,,pyn.Module.Exec(code);
,,,,return null;
,,,}
,}

,/// <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)
,,{
,,,string pyDll = @"C:\Program Files (x86)\Quick Macros 2\python312.dll";
,,,if (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("PYTHONNET_PYDLL"))) Runtime.PythonDLL = pyDll;

,,,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 (!string.IsNullOrEmpty(code)) 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
,,,//.NET 9+: BinaryFormatter serialization and deserialization have been removed
,,,//catch (PlatformNotSupportedException) { }
,,}
,}

,/// <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();
}


Messages In This Thread
RE: Execute Python Code in QM Using python.net - by Davider - 06-09-2025, 01:37 PM
RE: First steps with Python.NET - by Davider - 06-09-2025, 03:30 AM

Forum Jump:


Users browsing this thread: 1 Guest(s)