Search the Community
Showing results for 'Py_Begin_Allow_Threads'.
Found 22 results
-
Using Python4Delphi library in a Windows service
pyscripter replied to Luca Pretti's topic in Python4Delphi
In the demo project modify the CreateEngine function as follows: procedure TService1.CreatePyEngine; begin PythonEngine := TPythonEngine.Create(nil); PythonEngine.Name := 'PythonEngine'; PythonEngine.DLLName := 'python313.dll'; PythonEngine.DllPath := 'c:\python\python313\'; PythonEngine.PythonHome := PythonEngine.DLLPath; PythonEngine.VenvPythonExe := PythonEngine.DLLPath + 'python.exe'; // may be needed PythonEngine.RegVersion := '3.13'; PythonEngine.UseLastKnownVersion := False; PythonEngine.FatalAbort := False; PythonEngine.FatalMsgDlg := False; PythonEngine.LoadDll; TPythonThread.Py_Begin_Allow_Threads; end; I think this should set the python path correctly and avoid import errors. -
Yes, I was really mistaken and the error is not where I previously thought the error was with LoadDll: procedure CreatePyEngine; begin PythonEngine := TPythonEngine.Create(nil); PythonEngine.LoadDll; // CRASH HERE //TPythonThread.Py_Begin_Allow_Threads; end;
-
How to run one .py script in several instances at the same time ?
Celebr0 posted a topic in Python4Delphi
Hello, I am faced with a problem that I need to run one .py script in several instances, but I can’t achieve this through python4delphi ( I'm trying to do it like this, but since the script has been running for some time, the program just crashes: program ParallelPython; {$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils, System.Diagnostics, System.Variants, System.SyncObjs, PythonEngine; var PythonEngine: TPythonEngine; type TPyThread = class(TPythonThread) protected procedure ExecuteWithPython; override; public constructor Create(createsuspended:boolean); end; procedure CreatePyEngine; begin PythonEngine := TPythonEngine.Create(nil); PythonEngine.LoadDll; TPythonThread.Py_Begin_Allow_Threads; end; procedure DestroyEngine; begin TPythonThread.Py_End_Allow_Threads; PythonEngine.Free; end; procedure TPyThread.ExecuteWithPython; const Arg = 'import sys'+#13#10+ 'def run_python_script(args_str):'+#13#10+ ' args_list = args_str.split()'+#13#10+ ' sys.argv = [sys.argv[0]] + args_list'; begin inherited; while true do begin PythonEngine.ExecString(Arg); PythonEngine.ExecFile(extractfilepath(paramstr(0))+'script.py'); end; end; constructor TPyThread.Create(createsuspended:boolean); begin inherited Create(CreateSuspended); ThreadExecMode := emNewInterpreterOwnGIL; FreeOnTerminate := True; end; var I: Integer; begin try CreatePyEngine; for I := 1 to 10 do TPyThread.Create(False); finally //DestroyEngine; end; ReadLn; end. And it probably also crashes because the script is trying to be executed in one interpreter ( -
Hello, I ran into a problem that input/output does not work through the OnReceiveUniData/OnReceiveData event and others, but it works through TPythonGUIInputOutput.Output unit Unit2; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, PythonEngine, PythonGUIInputOutput; type TForm2 = class(TForm) Button1: TButton; Button2: TButton; Memo1: TMemo; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure OnReceiveUniData(Sender: TObject; var Data: string); procedure CreatePyEngine; private { Private declarations } public { Public declarations } end; var Form2: TForm2; PythonEngine: TPythonEngine; working: boolean = True; implementation {$R *.dfm} procedure TForm2.OnReceiveUniData(Sender: TObject; var Data: string); begin Memo1.Lines.Add(Data); //No Memo1.Lines.Add('2'); //No end; procedure TForm2.CreatePyEngine; var pyio:TPythonGUIInputOutput; begin pyio := TPythonGUIInputOutput.Create(nil); pyio.UnicodeIO := True; pyio.DelayWrites := True; pyio.OnReceiveUniData := OnReceiveUniData; //pyio.Output:=Memo1; //------- WORK PythonEngine := TPythonEngine.Create(nil); PythonEngine.IO := pyio; PythonEngine.RedirectIO := True; PythonEngine.LoadDll; TPythonThread.Py_Begin_Allow_Threads; end; procedure TForm2.Button1Click(Sender: TObject); const Script ='print("Hello")'; begin CreatePyEngine; // TThread.CreateAnonymousThread( procedure var Py: IPyEngineAndGIL; begin Py := SafePyEngine; while working do PythonEngine.ExecString(Script); end).Start; end; procedure TForm2.Button2Click(Sender: TObject); begin working:=False; end; end.
-
Big Thanks This Is Work: procedure TForm2.OnData(Sender: TObject; const Data: string); begin Memo1.Lines.Add(Data); end; procedure TForm2.CreatePyEngine; var pyio:TPythonInputOutput; begin pyio := TPythonInputOutput.Create(nil); pyio.UnicodeIO := True; pyio.DelayWrites := False; pyio.OnSendUniData := OnData; PythonEngine := TPythonEngine.Create(nil); PythonEngine.IO := pyio; PythonEngine.RedirectIO := True; PythonEngine.LoadDll; TPythonThread.Py_Begin_Allow_Threads; end;
-
Too Not work procedure TForm2.OnData(Sender: TObject; const Data: string); begin Memo1.Lines.Add(Data); //No Memo1.Lines.Add('2'); //No end; procedure TForm2.CreatePyEngine; var pyio:TPythonInputOutput; begin pyio := TPythonInputOutput.Create(nil); pyio.UnicodeIO := True; pyio.DelayWrites := True; pyio.OnSendUniData := OnData; //pyio.Output:=Memo1; //------- WORK PythonEngine := TPythonEngine.Create(nil); PythonEngine.IO := pyio; PythonEngine.RedirectIO := True; PythonEngine.LoadDll; TPythonThread.Py_Begin_Allow_Threads; end;
-
Hello, it still doesn't work =( procedure TForm2.CreatePyEngine; var pyio:TPythonInputOutput; begin pyio := TPythonInputOutput.Create(nil); pyio.UnicodeIO := True; pyio.DelayWrites := True; pyio.OnReceiveUniData := OnReceiveUniData; //pyio.Output:=Memo1; //------- WORK PythonEngine := TPythonEngine.Create(nil); PythonEngine.IO := pyio; PythonEngine.RedirectIO := True; PythonEngine.LoadDll; TPythonThread.Py_Begin_Allow_Threads; end;
-
I did not, I thought that was actually done using the ThreadPythonExec as well as in this: FTask := TTask.Create( procedure var Py: IPyEngineAndGIL; begin Py := SafePyEngine; Py.PythonEngine.ExecStrings(Script); end); FTask.Start; So no matter what I am required to call Py_Begin_Allow_Threads and Py_End_Allow_Threads?
-
@maomao2028 Works fine here without memory leaks. See attached project. Note the use of DelayWrites := True in the PythonGUIInputOutput and the calls to TPythonThread.Py_End_Allow_Threads and TPythonThread.Py_Begin_Allow_Threads. Demo01.zip
-
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
-
don't works import pandas or openpyxl in TPythonThread (delphi)
pyscripter replied to Nefari0's topic in General Help
Please post questions regarding P4D to the Third Party P4D support forum. What is this InitThread? Using python threads requires deep knowledge of the Python API and the complexities of GIL. If do have to use threads, please study Demo 11 and the related posts in the P4D forum Showing results for 'Py_Begin_Allow_Threads'. - Delphi-PRAXiS [en] (delphipraxis.net) -
HELP ,can not run torch scipt but can be run in Python environment
pyscripter replied to tomye's topic in Python4Delphi
Why are you making things complicated? Follow the KISS rule. Using threads in this way requires deep knowledge of the Python API and the complexities of GIL. If do have to use threads, please study Demo 11 and the related posts in this forum Showing results for 'Py_Begin_Allow_Threads'. - Delphi-PRAXiS [en] (delphipraxis.net) -
HELP ,can not run torch scipt but can be run in Python environment
tomye replied to tomye's topic in Python4Delphi
i found this issue comes from the P4D thread mode i am not sure if it is P4D BUG because now i can run the script in P4D Demo01 after i PIP INSTALL PYSQLITE3, but still can not be run in my project, will raise an error: could not find cudnn_adv_infer64_8.dll or one of its dependent file the cudnn_adv_infer64_8.dll and all of its dependent files are existing as i said, i set TPythonThread.Py_Begin_Allow_Threads; in my code, and all running are in thread mode, i don't know if the Python path is lost in thread mode -
HELP ,can not run torch scipt but can be run in Python environment
tomye replied to tomye's topic in Python4Delphi
actually , i don't know why the torch uses the SQLite, however , i searched the DLL files, they are all there and all of them are 64bit and this error message ( Not a valid win32 application ) is only appear on P4D Demo01, but in my project, there is another error message the error message is : OSError: [WinError 127] The specified program could not be found same script i could run it in Python envirnoment, but can not be run in P4D , BTW, my project uses P4D thread mode ( TPythonThread.Py_Begin_Allow_Threads; ) and then i test the script in P4D Demo01, got an another error message: Not a valid win32 application 😞 -
class procedure TPythonThread.Py_Begin_Allow_Threads; You also need to call Py_End_Allow_Threads when all threads finish.
-
Xdata Rest server request & Python4Delphi
pyscripter replied to J. Robroeks's topic in Python4Delphi
I said "after loading" loosely speaking and not "in the OnAfterLoad event". Indeed you can only call Py_Begin_Allow_Threads after the engine is initialized. I have not tested, but you can set AutoFinalize to False and in the OnBeforeUnload do Py_End_Allow_Threads; Finalize; Also probably, skipping the above when the application closes down may not be necessary. -
To be exact, Py_Begin_Allow_Threads should be called inside PythonEngine.OnAfterInit event, NOT OnAfterLoad event as advised by @pyscripter. Otherwise, error will be thrown, because the gPythonEngine at this point is still nil. Py_End_Allow_Threads should NOT be called inside OnBeforeUnload event. If put inside OnBeforeUnload event, an access violation error will be thrown - because Py_Finialize will be called BEFORE OnBeforeUnload, thus would trigger an access violation error at the point where Py_Finalize is called, which is before firing OnBeforeUnload event. I think a new event OnBeforeFinalize should be added, to address this problem. @pyscripter What am I missing here?
-
Xdata Rest server request & Python4Delphi
pyscripter replied to J. Robroeks's topic in Python4Delphi
Of course it is. If another thread holds the lock, PyGILState_Ensure blocks until the GIL becomes available, i.e. the holding thread calls PyGILState_Release. If more than one threads are waiting for GIL then I think it is assigned of FCFS basis. The automatic switching that you described only applies to threads created with the threading code. All other threads need to get the GIL before executing python code and then release it. Yes you do need to call Py_Begin_Allow_Threads in the main thread. When the python DLL loads, the main thread owns the GIL and it needs to release it before other threads can execute python code. -
I am still somewhat confused - if I call PyGILState_Ensure in one thread, will that block other threads calling PyGILState_Ensure? If I use your utility function IPyEngineAndGIL, do I still need to call TPythonThread.Py_Begin_Allow_Threads (calls PyEval_SaveThread) in the main thread, after loading the Python DLL? Thank you.
-
I am still somewhat confused - if I call PyGILState_Ensure in one thread, will that block other thread calling PyGILState_Ensure? If I use your utility function IPyEngineAndGIL, do I still need to call TPythonThread.Py_Begin_Allow_Threads (calls PyEval_SaveThread) in the main thread, after loading the Python DLL? Thank you.
-
Xdata Rest server request & Python4Delphi
pyscripter replied to J. Robroeks's topic in Python4Delphi
None of the python code is blocking other threads. But the following functions are blocking: PyGILState_Ensure PyEval_RestoreThread In other words you need to get and hold to the GIL to execute any python code. So take for example sleep. It works like windows sleep. But to let other threads to execute python code you need to use Py_Begin_Allow_Threads /Py_End_Allow_Threads before/after the sleep. Python deals with the threads it creates. (threading module). -
Xdata Rest server request & Python4Delphi
pyscripter replied to J. Robroeks's topic in Python4Delphi
In your code above you should destroy PY_SUBJECT before releasing the GIL Python has a lesser known feature called sub-interpreters, which allows you to use the interpreter from a clean state. This is what emNewInterpreter does. Normally I would not bother with that. The pattern you need to follow using the latest version of P4D: In your main thread to release the GIL after loading the Python dll: TPythonThread.Py_Begin_Allow_Threads (calls PyEval_SaveThread) In your Delphi threads including the main thread (or if you use ITask or TParallel) that execute python code (this is what TPythonThread does): fGILState := .PyGILState_Ensure; try Do python staff finally PyGILState_Release(fGILState); end; In your main thread before unlolading Python TPythonThread.Py_End_Allow_Threads (calls PyEval_RestoreThread) if you have a long running thread that does python stuff and you want allow other threads to do python stuff as well then the pattern is: fGILState := .PyGILState_Ensure; try Do python staff TPythonThread.Begin_Allow_Threads; try Other threads can run python code finally TPythonThread.End_ALlow_Threads; end; Do more python stuff. finally PyGILState_Release(fGILState); end; In PyScripter I have a utility function: type IPyEngineAndGIL = interface function GetPyEngine: TPythonEngine; function GetThreadState: PPyThreadState; property PythonEngine: TPythonEngine read GetPyEngine; property ThreadState: PPyThreadState read GetThreadState; end; function SafePyEngine: IPyEngineAndGIL; begin Result := TPyEngineAndGIL.Create end; type TPyEngineAndGIL = class(TInterfacedObject, IPyEngineAndGIL) fPythonEngine: TPythonEngine; fThreadState: PPyThreadState; fGILState: PyGILstate_STATE; private function GetPyEngine: TPythonEngine; function GetThreadState: PPyThreadState; public constructor Create; destructor Destroy; override; end; { TPyEngineAndGIL } constructor TPyEngineAndGIL.Create; begin inherited Create; fPythonEngine := GetPythonEngine; fGILState := fPythonEngine.PyGILState_Ensure; fThreadState := fPythonEngine.PyThreadState_Get; end; destructor TPyEngineAndGIL.Destroy; begin fPythonEngine.PyGILState_Release(fGILState); inherited; end; function TPyEngineAndGIL.GetPyEngine: TPythonEngine; begin Result := fPythonEngine; end; function TPyEngineAndGIL.GetThreadState: PPyThreadState; begin Result := fThreadState; end; which is used in the main or other threads as: var Py: IPyEngineAndGIL; begin Py := SafePyEngine; Py.Engine. whenever I need to execute Python code