• XSS.stack #1 – первый литературный журнал от юзеров форума

Python4Delphi прошу помощи

triblekill

RAID-массив
Забанен
Регистрация
24.05.2023
Сообщения
62
Решения
1
Реакции
17
Пожалуйста, обратите внимание, что пользователь заблокирован
Здрасте, удалось ли кому то победить библиотеку Python4Delphi у меня она напрочь отказывается работать в многопотоке:

Код:
{$APPTYPE CONSOLE}

uses
  SysUtils,
  Classes,
  System.syncobjs,
  PythonEngine;

type
  th = class(TPythonThread)
  private
  protected
    procedure Execute; Override;
  public
    constructor Create(CreateSuspended: Boolean);
  end;

var
  cs: TCriticalSection;
  PythonEngine:TPythonEngine;

{ th }

constructor th.Create(CreateSuspended: Boolean);
begin
  inherited Create(CreateSuspended);
  ThreadExecMode := emNewInterpreter;
  FreeOnTerminate := True;
end;

procedure th.Execute;
var
scr,val: string;
PyFunc: PPyObject;
begin
  inherited;
while True do
begin
PythonEngine.ExecString('HW="Hello World!";');
cs.Enter;
Writeln(PythonEngine.EvalStringAsStr('HW')); // Вывод значения в консоль
cs.Leave;
//pyfunc:=PythonEngine.FindFunction(PythonEngine.ExecModule,'');
//PythonEngine.Py_DecRef(PyFunc);
end;
//PythonEngine.PyEval_AcquireThread(Self.ThreadState);
//PythonEngine.PyErr_SetString(PythonEngine.PyExc_KeyboardInterrupt^, 'Terminated');
//PythonEngine.PyEval_ReleaseThread(Self.ThreadState);
end;

var
  i: Integer;
begin
  PythonEngine:=TPythonEngine.Create(nil);
  PythonEngine.InitThreads := True;
  PythonEngine.DllPath := ExtractFilePath(ParamStr(0)) + '\python';
  PythonEngine.DllName := 'python310.dll';
  PythonEngine.UseLastKnownVersion := False;
  PythonEngine.AutoLoad := False;
  PythonEngine.AutoFinalize := True;
  PythonEngine.AutoUnload := False;
  PythonEngine.RedirectIO := False;
  PythonEngine.LoadDll;
  Randomize;
  cs := TCriticalSection.Create;
 for i := 1 to 4 do
  th.Create(False);
  readln;
end.

В 1-2 потока иногда работает и то праздникам
 
Проблема не в библиотеке, а в самом интерпретаторе питона - который ты запускаешь внутри этой библиотеки. Поздравляю ты столкнулся с GIL. Теперь осталось понять зачем тебе тут нужен python?
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Проблема не в библиотеке, а в самом интерпретаторе питона - который ты запускаешь внутри этой библиотеки. Поздравляю ты столкнулся с GIL. Теперь осталось понять зачем тебе тут нужен python?
Я прочитал про блокировки GIL а разве:
PythonEngine.InitThreads := True;
Не автоматом это делает ?
 
PythonEngine.InitThreads := True;
Нет :) Просто советую юзать multiprocessing библиотеку под питон. Вообще не знаю что тебе в питоне понадобилось, что бы с паскалем его скрещивать :(
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Вообще не знаю что тебе в питоне понадобилось, что бы с паскалем его скрещивать
Мне понадобилось с криптой нормально работать, а на паскале ничего нету готового разве что можно под биткоин собрать алгоритм, на остальные монеты нет =)
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Поздравляю ты столкнулся с GIL
Прочитал TPythonThread автоматом выставляет GIL блокировки, разблокировки
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Вот так как то через раз работает, но всё равно не стабильно:

Код:
{$APPTYPE CONSOLE}

uses
  SysUtils,
  Classes,
  System.syncobjs,
  PythonEngine;

type
  th = class(TPythonThread)
  private
  protected
    procedure Execute; Override;
  public
    constructor Create(CreateSuspended: Boolean);
  end;

var
  cs: TCriticalSection;
  PythonEngine:TPythonEngine;

{ th }

constructor th.Create(CreateSuspended: Boolean);
begin
  inherited Create(CreateSuspended);
  ThreadExecMode := emNewInterpreter;
  FreeOnTerminate := True;
end;

procedure th.Execute;
var
PyFunc: PPyObject;
GILState:PyGILstate_STATE;
OwnThreadState: PPyThreadState;
begin
  inherited;
while True do
begin
Py_Begin_Allow_Threads;
Py_End_Allow_Threads;
OwnThreadState:=PythonEngine.PyEval_SaveThread;
gilstate  :=  PythonEngine.PyGILState_Ensure;
PythonEngine.ExecString('HW="Hello World!";');
cs.Enter;
Writeln(PythonEngine.EvalStringAsStr('HW'));
cs.Leave;
PythonEngine.PyGILState_Release(gilstate);
PythonEngine.PyEval_RestoreThread(OwnThreadState);
end;

end;

var
  i: Integer;
begin
  PythonEngine:=TPythonEngine.Create(nil);
  PythonEngine.InitThreads := True;
  PythonEngine.DllPath := ExtractFilePath(ParamStr(0)) + '\python';
  PythonEngine.DllName := 'python310.dll';
  PythonEngine.UseLastKnownVersion := False;
  PythonEngine.AutoLoad := False;
  PythonEngine.AutoFinalize := False;
  PythonEngine.AutoUnload := False;
  PythonEngine.RedirectIO := False;
  PythonEngine.LoadDll;
  Randomize;
  cs := TCriticalSection.Create;
 for i := 1 to 4 do
  th.Create(False);
  readln;
end.
 
Пожалуйста, обратите внимание, что пользователь заблокирован
О боже я это победил наконец методом танцев с бубнами и тыка =)
Вот если кому то когда то пригодится правильный подход :

Код:
{$APPTYPE CONSOLE}

uses
  SysUtils,
  Classes,
  System.syncobjs,
  PythonEngine;

type
  th = class(TPythonThread)
  private
  protected
    procedure Execute; Override;
  public
    constructor Create(CreateSuspended: Boolean);
  end;

var
  cs: TCriticalSection;
  PythonEngine:TPythonEngine;

{ th }

constructor th.Create(CreateSuspended: Boolean);
begin
  inherited Create(CreateSuspended);
  ThreadExecMode := emNewInterpreter;
  FreeOnTerminate := True;
end;

procedure th.Execute;
var
result:string;
FGILState: PyGILstate_STATE;
begin
  inherited;
while True do
begin
FGILState  :=  PythonEngine.PyGILState_Ensure;
PythonEngine.ExecString('HW="Hello World!"');
result:=PythonEngine.EvalStringAsStr('HW');
PythonEngine.PyGILState_Release(FGILState);
cs.Enter;
Writeln(result); // Вывод значения в консоль
cs.Leave;
end;
// По завершению ВСЕХ потоков вызовите Py_End_Allow_Threads;
end;

var
  i: Integer;
begin
  cs := TCriticalSection.Create;
  PythonEngine:=TPythonEngine.Create(nil);
  PythonEngine.InitThreads := True;
  PythonEngine.UseLastKnownVersion := False;
  PythonEngine.DllPath := ExtractFilePath(ParamStr(0)) + '\python';
  PythonEngine.DllName := 'python310.dll';
  PythonEngine.AutoLoad := False;
  PythonEngine.AutoFinalize := False;
  PythonEngine.AutoUnload := False;
  PythonEngine.RedirectIO := False;
  PythonEngine.LoadDll;
  TPythonThread.Py_Begin_Allow_Threads; //Важно вызвать в основном потоке один раз
 for i := 1 to 10 do
 th.Create(False);
 readln;
end.
 
Последнее редактирование:


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх