Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Execute Python Code in QM Using python.net
#1
I created a function, pycall2, which uses the python.net library to execute Python code in QM. I encountered two problems:

1.The print function in Python does not output anything.
2.When the parameters provided to the pycall2 function are incorrect, an exception occurs that causes the process to hang, and QM must be restarted.

Prerequisites for Running the pycall2 Function

1.Download the file from https://www.nuget.org/packages/pythonx86/3.12.7, change its extension to .zip, and copy all files from the tools folder inside the package to the QM installation directory.
2.Download the file from https://www.nuget.org/packages/pythonnet/3.0.5, change its extension to .zip, and copy the Python.Runtime.dll file from the package to the QM installation directory.
3.Set the PYTHONHOME and PYTHONPATH environment variables to the QM installation directory.
4.Use the following code for testing.

I have been using this function for some time, and it works well in most cases with minimal configuration required.
Thanks in advance for any suggestions and help.


Function pycall_T
 
Code:
Copy      Help
out

str pyCode=
;def func1(a1, a2, a3):
;;;;;return a1 * a2 + a3
;
;def func2(a1, a2):
;;;;;return a1 * a2
;
;def func3(a1, a2):
;;;;;return a1 + a2
;
;def noArgsFunc():
;,return 'no Args Func'
;
;def print2():
;,print('print output')

str f2="func2"; int a1(6) a2(7)
mes pycall2(pyCode, f2, a1, a2) ;;ok

mes pycall2(pyCode, "noArgsFunc") ;;ok

mes pycall2(pyCode, "print2") ;;no output

mes pycall2(pyCode, "8888888") ;;An error will occur, and the macro cannot be executed again unless qm is restarted.

Function pycall2
Code:
Copy      Help
function` str'pyCode [str'_Func] [`_A1] [`_A2] [`_A3] [`_A4] [`_A5]

CsScript x

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

x.AddCode("")

ARRAY(VARIANT) args.create
sel getopt(nargs)-2
,case 1 args[]=_A1
,case 2 args[]=_A1; args[]=_A2
,case 3 args[]=_A1; args[]=_A2; args[]=_A3
,case 4 args[]=_A1; args[]=_A2; args[]=_A3; args[]=_A4
,case 5 args[]=_A1; args[]=_A2; args[]=_A3; args[]=_A4; args[]=_A5

ret x.Call("py.pyCall" pyCode _Func args)

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

public class py
{
,public static object pyCall(string code, string func = null, params object[] args) 
,{
,,dynamic Rd = pyRun(code, func, args); 
,,object R = Rd.ToString();
,,PythonEngine.Shutdown();
,,return R;
,}

,public static dynamic pyRun(string code, string func = null, params object[] args)
,{
,,PythonEngine.Initialize();
,
,,using (Py.GIL())
,,{
,,,dynamic result;
,,,if (string.IsNullOrEmpty(func) && (args == null || args.Length == 0))
,,,{
,,,,// Redirect output
,,,,dynamic sys = Py.Import("sys"); 
,,,,dynamic io = Py.Import("io");
,,,,var output = io.StringIO(); // Create a new StringIO object
,,,,sys.stdout = output; // Redirect sys.stdout to the StringIO object
,,,,
,,,,PythonEngine.RunSimpleString(code);
,,,,
,,,,result = output.getvalue(); // Get the value from StringIO
,,,,sys.stdout = sys.__stdout__; // Restore the original output
,,,}
,,,else
,,,{
,,,,using (var scope = Py.CreateScope())
,,,,{
,,,,,if (args != null && args.Length > 0)
,,,,,{
,,,,,,var pyArgs = new PyObject[args.Length];
,,,,,,for (int i = 0; i < args.Length; i++)
,,,,,,{
,,,,,,,pyArgs[i] = args[i].ToPython();
,,,,,,}
,,,,,,scope.Exec(code);
,,,,,,result = scope.Get(func).Invoke(pyArgs);
,,,,,}
,,,,,else
,,,,,{
,,,,,,scope.Exec(code);
,,,,,,result = scope.Get(func).Invoke();
,,,,,}
,,,,}
,,,}
,,,return result;
,,}
,,// PythonEngine.Shutdown();
,}
}


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

Forum Jump:


Users browsing this thread: 1 Guest(s)