iqrf
Members-
Content Count
44 -
Joined
-
Last visited
Everything posted by iqrf
-
Hello, is it possible to somehow create a submodule. Something like this MainModule := TPythonModule.Create(nil); MainModule.ModuleName := 'spam'; SubModule := TPythonModule.Create(nil); SubModule.ModuleName := 'spam.test'; and call in Python import spam import spam.test spam.function1() spam.test.function2() it reports an error if i do it like this it's fine import spam import spam.test as T spam.function1() T.function2() Can it be solved somehow? Thanks for the ideas.
-
I finally found a way to make a package import importlib import types import sys # Package name package_name = 'my_package' # List of modules to be part of the package module_names = ['module1', 'module2'] # Create an empty package package = types.ModuleType(package_name) package.__path__ = [] # Import and add individual modules to the package for module_name in module_names: module = importlib.import_module(module_name) setattr(package, module_name, module) # Set __all__ to the list of module names package.__all__ = module_names # Add the package to the list of imported modules sys.modules[package_name] = package Then it is possible import my_package from my_package import module1 from my_package import module2 as T print(dir(module1)) print(dir(my_package.module1)) print(dir(T)) Only this import my_package.module1 as T is not possible. ModuleNotFoundError: No module named 'my_package.sub_module1' Does anyone know why?
-
Hi, I finally solved it at the Python level. I have two TPython modules, one named main_module and the other sub_module. Just add to the InitScript import main_module import sub_module main_module.sub_module = sub_module And you can use in Python main_module.sub_module.function1() but of course, also sub_module.function1(). In this way, a pseudo-hierarchical structure of modules can be created. Because this doesn't import main_module.sub_module as a test. main_module is not a package!
-
Hello, I have such a dictionary ... AddMethod( 'TestArray', @TPyPoint.DoTestArray, 'Point.TestArray()' ); function TPyPoint.DoTestArray(args : PPyObject): PPyObject; cdecl; type TDevice = record ValueA: Integer; ValueB: String; end; TDevices = array of TDevice; var DeviceArray: TDevices; I: Integer; DeviceList: PPyObject; DeviceDict: PPyObject; function TDeviceToPyObject(const Device: TDevice): PPyObject; var DeviceDict: PPyObject; begin with GetPythonEngine do begin DeviceDict := PyDict_New; PyDict_SetItemString(DeviceDict, 'ValueA', PyLong_FromLong(Device.ValueA)); PyDict_SetItemString(DeviceDict, 'ValueB', PyUnicodeFromString(PAnsiChar(AnsiString(Device.ValueB)))); Result := DeviceDict; end; end; begin SetLength(DeviceArray, 2); DeviceArray[0].ValueA := 1; DeviceArray[0].ValueB := 'Device 1'; DeviceArray[1].ValueA := 2; DeviceArray[1].ValueB := 'Device 2'; with GetPythonEngine do begin Adjust(@Self); DeviceList := PyList_New(0); for I := 0 to High(DeviceArray) do begin DeviceDict := TDeviceToPyObject(DeviceArray[I]); PyList_Append(DeviceList, DeviceDict); Py_DecRef(DeviceDict); end; Result := DeviceList; end; end; Is there any possibility to make the data read-only in Python? I can only do this if I pass them as Tuples using ArrayToPyTuple(MyArray), but then it's just a one-dimensional array. And one more question, how to pass TDevice data to Python so that it can be written in Python instead of this one a = spam.myPoint.TestArray() print(a[0]['ValueA']) print(a[0]['ValueB']) this one a = spam.myPoint.TestArray() print(a[0].ValueA) print(a[0].ValueB) Thanks.
-
Thanks, but understanding this code is beyond my abilities.
-
Hello, is there any way to remap PyErr_Print using a custom function? I would like to log the error output on a separate sheet. Now everything ends up in TPythonInputOutput. Or can it be done differently? Thanks for the idea.
-
Thanks, it works. try MaskFPUExceptions(True); PythonEngine1.ExecStrings(Memo1.Lines); except errorMessage := MainModule.mystderr.getvalue(); ErrorLog(errorMessage); end; I would just like to continuously catch errors if someone writes in the Python code for example print("Error example 1", file=sys.stderr) or sys.stderr.write("Error Example 2") The current solution only prints everything at once, with the same timestamp. Thanks.
-
I will answer myself, this is functional import builtins def myinput(prompt): builtins._input_prompt = prompt return builtins._input(prompt) builtins._input = builtins.input builtins.input = myinput Thanks again, I'm learning Python and I'm still amazed at what it can do.
-
Thanks a lot, the text is passed, but the input value is always NoneType. import builtins def myinput(prompt): builtins._input_prompt = prompt builtins._input(prompt) builtins._input = builtins.input builtins.input = myinput nadr = int(input('Enter device address (0 - 239, 255): ')) print(f'Node {nadr} is not bonded') procedure TForm1.PythonInputOutput1ReceiveUniData(Sender: TObject; var Data: string); var s: string; begin InputQuery( 'Query from Python', MainModule.builtins._input_prompt, s); Data := AnsiString(s); end; Enter device address (0 - 239, 255): Traceback (most recent call last): File "<string>", line 11, in <module> TypeError : int() argument must be a string, a bytes-like object or a real number, not 'NoneType'
-
How to override builtins.input please?
-
Hi, According to Demo33, we edited Demo01 to run the script in a thread using the Start and Stop buttons.. PythonGUIInputOutput1 replaced PythonInputOutput1. unit Unit1; interface uses Classes, SysUtils, Windows, Messages, Graphics, Controls, Forms, Dialogs, StdCtrls, ComCtrls, ExtCtrls, System.Math,System.SyncObjs, PythonEngine, Vcl.PythonGUIInputOutput; type TPyThread = class(TPythonThread) protected procedure ExecuteWithPython; override; end; TForm1 = class(TForm) PythonEngine1: TPythonEngine; Memo1: TMemo; Panel1: TPanel; Button1: TButton; Splitter1: TSplitter; Button2: TButton; Button3: TButton; OpenDialog1: TOpenDialog; SaveDialog1: TSaveDialog; PythonGUIInputOutput1: TPythonGUIInputOutput; Memo2: TMemo; PythonInputOutput1: TPythonInputOutput; Button4: TButton; Button5: TButton; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure Button3Click(Sender: TObject); procedure PythonInputOutput1SendUniData(Sender: TObject; const Data: string); procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure Button4Click(Sender: TObject); procedure Button5Click(Sender: TObject); private FCriticalSection : TCriticalSection; PyThread: TPyThread; procedure ThreadDone(Sender: TObject); { Déclarations privées } public { Déclarations publiques } end; var Form1: TForm1; implementation {$R *.DFM} procedure TPyThread.ExecuteWithPython; begin inherited; Form1.PythonEngine1.ExecString(UTF8Encode(Form1.Memo1.Text)); end; procedure TForm1.ThreadDone(Sender: TObject); begin TPythonThread.Py_End_Allow_Threads; end; procedure TForm1.Button1Click(Sender: TObject); var s: String; begin MaskFPUExceptions(True); PythonEngine1.ExecStrings(Memo1.Lines); end; procedure TForm1.Button2Click(Sender: TObject); begin with OpenDialog1 do begin if Execute then Memo1.Lines.LoadFromFile( FileName ); end; end; procedure TForm1.Button3Click(Sender: TObject); begin with SaveDialog1 do begin if Execute then Memo1.Lines.SaveToFile( FileName ); end; end; procedure TForm1.Button4Click(Sender: TObject); begin TPythonThread.Py_Begin_Allow_Threads; PyThread := TPyThread.Create(True); PyThread.FreeOnTerminate := True; PyThread.OnTerminate := ThreadDone; PyThread.Start; end; procedure TForm1.Button5Click(Sender: TObject); begin if Assigned(PyThread) and (not PyThread.Finished) then begin GetPythonEngine.PyEval_AcquireThread(PyThread.ThreadState); GetPythonEngine.PyErr_SetString(GetPythonEngine.PyExc_KeyboardInterrupt^, 'Terminated'); GetPythonEngine.PyEval_ReleaseThread(PyThread.ThreadState); while not PyThread.Finished do application.ProcessMessages; end; end; procedure TForm1.FormCreate(Sender: TObject); begin FCriticalSection := TCriticalSection.Create; end; procedure TForm1.FormDestroy(Sender: TObject); begin if Assigned(PyThread) and (not PyThread.Finished) then Button5Click(Sender); FCriticalSection.Free; end; procedure TForm1.PythonInputOutput1SendUniData(Sender: TObject; const Data: string); begin fCriticalSection.Enter; try TThread.ForceQueue(nil, procedure begin memo2.Lines.Add(data); end); finally fCriticalSection.Leave; end; Sleep(1); end; end. If I run this script, everything is OK from datetime import datetime import time while True: time.sleep(0.1) print(datetime.now()) 2023-04-24 12:24:21.726342 2023-04-24 12:24:21.834341 2023-04-24 12:24:21.943236 2023-04-24 12:24:22.051522 Traceback (most recent call last): File "<string>", line 8, in <module> KeyboardInterrupt: Terminated If this one from datetime import datetime import time while True: print(datetime.now()) so i get an error 2023-04-24 12:44:57.749385 2023-04-24 12:44:57.764722 2023-04-24 12:44:57.780558 2023-04-24 12:44:57.796288 2023-04-24 12:44:57.811762 KeyboardInterrupt: Terminated The above exception was the direct cause of the following exception: Traceback (most recent call last): File "<string>", line 5, in <module> SystemError: <function DebugOutput.write at 0x03FF6758> returned a result with an exception set Please how to get rid of this error. Thank you
-
Unfortunately SystemError: <DebugOutput.write function happens even if I catch the KeyboardInterrupt in a python script or in Delphi. I am attaching a test application. If I insert a sleep mode (0,1) before printing, the error does not appear. If I put sleep(0.08) sometimes it throws SystemError: <function DebugOutput.write sometimes SystemError: <builtin sleep function> returned a result with an exception set The value of sleep when the error does not occur will depend on the speed of the computer. Thanks Demo01.zip
-
Yes, I end with GetPythonEngine.PyEval_AcquireThread(PyThread.ThreadState); GetPythonEngine.PyErr_SetString(GetPythonEngine.PyExc_KeyboardInterrupt^, 'Terminated'); GetPythonEngine.PyEval_ReleaseThread(PyThread.ThreadState); I am having trouble terminating a thread using PyThread.Terminate. It doesn't work in the Demo33 example either. Why? I don't mean the KeyboardInterrupt: Terminated exception, that's ok. My point is that in the case of this script, where there is no wait time, another exception will be thrown while True: print(datetime.now()) SystemError: <function DebugOutput.write at 0x02C56758> returned a result with an exception set --------------------------- Debugger Exception Notification --------------------------- Project Demo01.exe raised exception class EPySystemError with message 'SystemError: <function DebugOutput.write at 0x02C56758> returned a result with an exception set'. --------------------------- Break Continue Help Copy --------------------------- It looks like the python engine is trying to write to DebugOutput at the moment when the thread is already canceled. If there is a wait in the script, the error will not occur. Thanks a lot for your help.
-
I modified as per the SimpleDemo but I still get the same error when exiting the thread procedure TForm1.PythonInputOutput1SendUniData(Sender: TObject; const Data: string); var ScheduleWrite: Boolean; begin if Data = '' then Exit; fCriticalSection.Enter; try ScheduleWrite := FOutputStream.Size = 0; FOutputStream.Write(Data[1], Length (Data) * 2); if ScheduleWrite then TThread.ForceQueue(nil, procedure var WS: string; begin fCriticalSection.Enter; try if fOutputStream.Size > 0 then begin SetLength(WS, fOutputStream.Size div 2); fOutputStream.Position := 0; fOutputStream.Read(WS[1], Length(WS) * 2); fOutputStream.Size := 0; if (Memo2.Lines.Count > 0) and (Memo2.Lines[Memo2.Lines.Count -1] <> '') then Memo2.Lines.BeginUpdate; try Memo2.Lines.Add(''); Memo2.Text := Memo2.Text + WS; // Memo2.Lines.GoToTextEnd; finally Memo2.Lines.EndUpdate; end; end; finally fCriticalSection.Leave; end; end); finally fCriticalSection.Leave; end; Sleep(1); end; 2023-04-24 18:00:05.560557 2023-04-24 18:00:05.575824 KeyboardInterrupt: Terminated The above exception was the direct cause of the following exception: Traceback (most recent call last): File "<string>", line 8, in <module> SystemError: <function DebugOutput.write at 0x02C56758> returned a result with an exception set
-
Calling a user exception defined in the external exceptions.py file
iqrf posted a topic in Python4Delphi
Hi, in demo34 there is an example of using a user Exception with PythonModule1.Errors.Add do begin Name := 'PointError'; ErrorType := etClass; end; GetModule.RaiseError( 'PointError', 'this is an example of raising an error !' ); Is there any way to use the definitions of exceptions from an external exception.py file and call them with GetModule.RaiseError? class RequestNadrInvalidError(ValueError): """ Invalid NADR value. This error is raised whenever a request object receives address that is out of allowed range ([C]: 0, [N]: 1-239). """ pass class RequestHwpidInvalidError(ValueError): """ Invalid HWPID value. This error is raised whenever a request object receives HWPID that is out of allowed range (0-65535 / 0x00-0xFF). """ pass class RequestParameterInvalidValueError(ValueError): """ Invalid request parameter value. This error is raised whenever a request object receives a parameter with value outside of it's defined domain. """ pass Thanks -
Hi, I'm completely new to P4D and trying to pass a python object to delphi as a function parameter with no success. Python: import delphi class myclass: def __init__(self, x, y): self.x = x + y def increment(self): self.x += 1 def get_x(self): return self.x if __name__ == '__main__': testC = myclass(1, 2) testC.increment() print(testC.get_x()) test = delphi.test test.send(testC) # raised exception class EPyTypeError with message 'TypeError: "Send" called with invalid arguments. Error: Could not find a method with compatible arguments'. Delphi: {$METHODINFO ON} TTest = class(TPersistent) private public procedure Send(AObject: PyObject); published end; {$METHODINFO OFF} procedure TTest.Send(AObject: PyObject); begin //I don't know how to get the x value of myclass here //showmessage(x.toString); end; ... ... var test: TTest; p: PPyObject; begin test := TTest.Create; p := PyDelphiWrapper.Wrap(test, soOwned); PythonModule.SetVar('test', p ); GetPythonEngine.ExecString(UTF8Encode(sePythonCode.Text)); end; Many thanks ahead. Petr
-
Passing a python object to a delphi function parameter
iqrf replied to iqrf's topic in Python4Delphi
The a great document, thanks a lot. -
Passing a python object to a delphi function parameter
iqrf replied to iqrf's topic in Python4Delphi
HI, I took inspiration from Demo34 and did what I needed. Everything works. I just want to ask why it is necessary to call Adjust(@Self); Do I have to worry about releasing the created PyBytes in TPyPoint.DoReceive using Py_XDECREF(pyBytes) or will Python take care of that? Thanks function TPyPoint.DoSend(args : PPyObject) : PPyObject; var data: TBytes; pyBytes: PPyObject; function PyBytesAsBytes(Obj: PPyObject): TBytes; var size: NativeInt; buffer: PAnsiChar; arr: TBytes; begin Result := Default(TBytes); with GetPythonEngine do begin if not PyBytes_Check(Obj) then Exit; PyBytes_AsStringAndSize(Obj, buffer, size); if (size = 0) then Exit; SetLength(Result, size); CopyMemory(Result, buffer, size); end; end; begin with GetPythonEngine do begin Adjust(@Self); if PyArg_ParseTuple( args, 'S:Point.Send', @pyBytes ) <> 0 then begin data := PyBytesAsBytes(pyBytes); // .... Result := ReturnNone; end else Result := nil; end; end; function TPyPoint.DoReceive(args : PPyObject) : PPyObject; var pyBytes: PPyObject; data: TBytes; begin with GetPythonEngine do begin Adjust(@Self); SetLength(data, 5); data[0] := 65; data[1] := 66; data[2] := 67; data[3] := 68; data[4] := 69; PyBytes := PyBytes_FromStringAndSize(PAnsiChar(data), Length(data)); Result := pyBytes; end; end; import spam d = bytes([0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6]) spam.myPoint.Send(d) print(list(d)) d = spam.myPoint.Receive() print(list(d)) -
Passing a python object to a delphi function parameter
iqrf replied to iqrf's topic in Python4Delphi
Yes it can be done using events or just like this test.send(testC.get_x()) procedure Send(Data: Variant); My point is to pass a python object and then call its function in Delphi.