Jump to content
Soulflesh

Running Python scripts in threads

Recommended Posts

Hi,

 

I have a problem running Python scripts in threads.

The execution stucks in TPythonThread.Execute --> gilstate := PyGILState_Ensure(); and never return.

Here is my example console application.

program p4dtest;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  System.SysUtils,
  System.Classes,

  PythonEngine;

type
  TMyPythonThread = class(TPythonThread)
  protected
    procedure ExecuteWithPython; override;
  public
    constructor Create;
  end;

  TMyServiceHelper = class
  public
    ThreadCount : Integer;
  public
    procedure ThreadDone(Sender: TObject);
  end;

{ TMyPythonThread }

constructor TMyPythonThread.Create;
begin
  Self.ThreadExecMode  := emNewInterpreter;
  Self.FreeOnTerminate := true;

  inherited Create(true);
end;

procedure TMyPythonThread.ExecuteWithPython;
begin
  Writeln('Test1');
  GetPythonEngine.ExecString('print("Test2")');
end;

{ TMyServiceHelper }

procedure TMyServiceHelper.ThreadDone(Sender: TObject);
begin
  Dec(ThreadCount);
end;

var
  MyPythonEngine  : TPythonEngine;
  MyPyInOut       : TMyPythonGUIInputOutput;
  MySvcHelper     : TMyServiceHelper;
  Threads         : Array of TMyPythonThread;
  i               : Integer;

begin
  try
    MyPythonEngine := TPythonEngine.Create(nil);
    MySvcHelper    := TMyServiceHelper.Create;
    try
      MyPythonEngine.InitThreads := true;
      MyPythonEngine.LoadDll;

      MySvcHelper.ThreadCount := 1;
      SetLength(Threads,1);
      for i:=0 to 0 do
      begin
        Threads[i] := TMyPythonThread.Create;
        Threads[i].OnTerminate := MySvcHelper.ThreadDone;
        Threads[i].Start;
      end;

      repeat
        CheckSynchronize;
        sleep(10);
      until MySvcHelper.ThreadCount = 0;

      Writeln('Done');
      ReadLn;
    finally
      FreeAndNil(MyPythonEngine);
      FreeAndNil(MySvcHelper);
    end;
  except
    on E: Exception do
    begin
      Writeln(E.ClassName, ': ', E.Message);
      ReadLn;
    end;
  end;
end.

 

Any ideas?

Best regards.

Share this post


Link to post

Unfortunately I cannot find anything like "PyBeginAllowThreads" or "AllowThreads" in all sources... 🤔

Share this post


Link to post
3 hours ago, Soulflesh said:

Unfortunately I cannot find anything like "PyBeginAllowThreads" or "AllowThreads" in all sources

class procedure TPythonThread.Py_Begin_Allow_Threads;

 

You also need to call Py_End_Allow_Threads when all threads finish.

Edited by pyscripter
  • Thanks 1

Share this post


Link to post

Additional question: 😀

 

I did some performance tests and unfortunately came to the expected result that normal thread processing does not bring any significant performance benefits.

For my test I used the Fibonacci algorithm to generate a high CPU load and a low IO load. 

 

Are there ways, apart from additional processes, to improve the performance of parallel processing?

I am talking here in the context of processing a wide variety of scripts or problems that cannot be parallelized themselves.

 

Is there a possibility to use Python derivatives like CPython or IronPython without or with a disableableable GIL?

 

From another area of resource sharing of dll libraries, a viable way was to duplicate the dll's and load them multiple times.

Would this also be a possible approach here with Python and Delphi? 

 

Best regards

Share this post


Link to post

Hard to answer this question in a meaningful way, since it depends a great deal on what you are trying to do.  In general though:

Edited by pyscripter

Share this post


Link to post

My topic is more in the sense of a web service, whereby it is more a matter of the overall speed and less of that of individual processes. In my view, true parallelism is the only way here.

Share this post


Link to post

Hello,

 

I'm looking for something similar - implementing python scripts in webservice procedures. Were You able to find a solution for this and would You mind to share it?

 

Regards

Harald

Share this post


Link to post
19 minutes ago, hschmid67 said:

I'm looking for something similar - implementing python scripts in webservice procedures. Were You able to find a solution for this and would You mind to share it?

Why are you looking to use threads? What problem are you trying to solve with threads? Are you aware of the impact of the Python GIL? 

  • Like 1

Share this post


Link to post
3 hours ago, hschmid67 said:

Hello,

 

I'm looking for something similar - implementing python scripts in webservice procedures. Were You able to find a solution for this and would You mind to share it?

 

Regards

Harald

Hello Harald,

 

Unfortunately, I have not yet found a way to implement this. 
I think at the moment the only possibility would be, as I wrote at the time, to multiply the dlls and then load them several times so that you have an independent dll environment for each thread.  

However, this would probably mean quite a lot of effort to rewrite this in the core libraries.

 

Many greetings

Share this post


Link to post
On 7/17/2021 at 5:07 PM, Soulflesh said:

I did some performance tests and unfortunately came to the expected result that normal thread processing does not bring any significant performance benefits.

Threads are evil. Threading was never originally intended for general parallel processing. In Python, what you want is multiprocessing; performant and safe. Threading in Python will only improve IO-intensive tasks.

 

Share this post


Link to post
On 7/17/2021 at 6:45 PM, pyscripter said:

you can code performance critical computations in Delphi. See python4delphi/Tutorials/Webinar I at master · pyscripter/python4delphi (github.com) for an example of speeding up python code 60 times doing this.

Ooh thanks; this will be very interesting to check out. I sometimes use Cython or jitted Python (Numba) to speed up old Delphi or FreePascal code. :classic_biggrin:

Share this post


Link to post
On 11/5/2021 at 9:29 AM, David Heffernan said:

Why are you looking to use threads? What problem are you trying to solve with threads? Are you aware of the impact of the Python GIL? 

Hello,

I have a REST web server written in XData (TMS) and would like to execute a Python script in a service request (ActiveDirectory - using pyad). This would be in a thread - and I cannot be sure that there would not be a parallel request that executes Python in a different thread...

So it seems to me that the only way to prevent problems with parallel python calls would be to use an object pool for python requests with just one element in the pool. The other request has to wait for the first to finish...

Regards
Harald

Share this post


Link to post

Hello,

I want to make API server via Delphi, run Python code per http requests at same time ...

Can I do it with Delphi and Python ? 

thanks

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×