Python und Lazarus

Python in C/C++ embedden, C-Module, ctypes, Cython, SWIG, SIP etc sind hier richtig.
Antworten
maurog
User
Beiträge: 6
Registriert: Sonntag 26. März 2023, 10:26

Hallo, ich habe mit Python wirklich keine Erfahrung.

Ich habe durch Python4Delphi Komponenten, Python Schnittstelle zu meinem Free Pascal Programm hinzugefügt.
Ich kann aus meinem Programm heraus ganz normal Python Skripte ausführen. Funktioniert tadellos.

Nun Folgende Code startet thonny aber es wird eine neue Instanz von meinem Programm auch gestartet.
Danach hängt sich das Ganze auf.

Code: Alles auswählen

from thonny import launch
launch()
Irgend welche Ideen?
Danke.
Sirius3
User
Beiträge: 17737
Registriert: Sonntag 21. Oktober 2012, 17:20

Warum willst Du aus einem Pascal-Programm heraus eine Python-IDE starten?
Und natürlich geht es im Programmfluß nach Aufruf von `launch` nicht weiter, bis die IDE wieder beendet wird.
maurog
User
Beiträge: 6
Registriert: Sonntag 26. März 2023, 10:26

Hallo Sirius3,

Ich will Python als Runtime-Scripter einsetzen. Thonny hat einen integrierte Debugger etc.
Somit wird Scripterstelleung einfacher.

PyScripter ist auch ein Python-IDE. Wenn ich die Code:

Code: Alles auswählen

from thonny import launch
launch()
in PyScripter ausführe, funktioniert problemlos.
Das Problem hat wahrscheinlich mit meinem Pascal Programm oder meiner Python einstelleungen zu tun.
Ich werde weiterhin den Fehler suchen.

Danke für das Antwort.
LG. Mauro.
__deets__
User
Beiträge: 14522
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ich denke nicht, dass es da Einstellungen auf Python-Seite gibt. Was ich mir eher vorstellen kann ist eine Abhaengigkeit zu dem FreePascal-Programm. Wenn dieser launch zB implizit einen fork durchfuehrt, koennte da sowas bei rumkommen. Die Loesung (im Sinne das dieses Verhalten nicht auftritt) waere ggf die Nutzung von subprocess.Popen, um die IDE als wirklich eigenen Prozess zu starten. Aber das produziert uU mit dem gedachten Zweck einen Konflikt. Der Anwendungsfall klingt ein bisschen sehr komplex. Richtig debuggen kannst du in Thonny auch nicht, wenn du gleichzeitig noch eine andere GUI (dein Programm) laufen hast - das tritt sich alles auf die Fuesse.
maurog
User
Beiträge: 6
Registriert: Sonntag 26. März 2023, 10:26

Danke für die ausführliche Erklärung.

Wie ich vorher geschrieben habe, PyScripter ist auch eine Python-IDE (in Delphi also Object Pascal geschrieben).
Aus PyScripter, kann ich problemlos thonny starten und meine eigene Scripte mit thonny ausführen und debuggen.
Weil ich mit Python keine erfahrung habe, werde ich mir eine einfachere Lösung überlegen.
Danke noch ein mal, für die Unterstützung.
LG. Mauro.
nezzcarth
User
Beiträge: 1633
Registriert: Samstag 16. April 2011, 12:47

maurog hat geschrieben: Sonntag 26. März 2023, 15:49 Wie ich vorher geschrieben habe, PyScripter ist auch eine Python-IDE (in Delphi also Object Pascal geschrieben).
Wenn ich es richtig verstanden habe, geht es dir ja darum, in einem Freepascal Programm, das Python als Erweiterungs/Skriptsprache verwendet, einen komfortablen Editor dafür bereitzustellen. Da PyScripter ja bereits eine in Object Pascal geschriebene Python-IDE und zudem OpenSource ist: Kannst du die benötigten Funktionalitäten nicht daraus übernehmen und so nativ in dein Programm integrieren (wenn die Lizenz das gestattet)?
Benutzeravatar
grubenfox
User
Beiträge: 422
Registriert: Freitag 2. Dezember 2022, 15:49

maurog hat geschrieben: Sonntag 26. März 2023, 15:49 PyScripter ist auch eine Python-IDE (in Delphi also Object Pascal geschrieben).
Aus PyScripter, kann ich problemlos thonny starten und meine eigene Scripte mit thonny ausführen und debuggen.
Weil ich mit Python keine erfahrung habe, werde ich mir eine einfachere Lösung überlegen.
??? Vielleicht "meine eigene Scripte mit PyScripter ausführen und debuggen."?
maurog
User
Beiträge: 6
Registriert: Sonntag 26. März 2023, 10:26

nezzcarth:

Ja genau das meine ich.
---Kannst du die benötigten Funktionalitäten nicht daraus übernehmen und so nativ in dein Programm integrieren (wenn die Lizenz das gestattet)?
Das ist sicher eine gute Idee aber ob ich das für zwei Platforme (Win, Linux) zusammenbringe? Ich glaube eher nicht.
Daher die Idee Thonny. Thonny ist bereits Platformunabhängig.
Danke.

grubenfox:
Wenn ich PyScripter oder Thonny als externe Prozess starte, kann ich auf meiner Anwendung nicht zugreifen. (Ich weiss nicht ob es möglich ist oder wie umständlich)
Ich sollte entweder mit Thonny hin bekommen oder PyScripter portiteren(Genau wie nezzcarth beschrieben hat ).

Danke für eure Vorschläge.
Wenn ich eine Lösung habe, melde ich mich gerne wider.
LG. Mauro.
maurog
User
Beiträge: 6
Registriert: Sonntag 26. März 2023, 10:26

__deets__:

Das ganze, habe ich schon mit Delphi und TMS-Scripter (Pascal Runtimescripter) realisert.
Es funktioniert tadellos.
In Delphi arbeite ich mich TMS-Komponenten.
In Lazarus mit Python4Delphi Komponenten.
Mein Ziel ist, das Ganze, soweit wie möglich, Platformunabhänging realisieren.
Daher FPC, Lazarus und Python.
FreeCAD arbeitet auch so ähnlich.

Hier ist ein Link https://www.youtube.com/watch?v=BnRZbmbFYj4 zur fertigen Anwendung in Delphi (wenn es gegen Forumregeln ist, den Link bitte einfach löschen)

Danke.
maurog
User
Beiträge: 6
Registriert: Sonntag 26. März 2023, 10:26

Also, Thonny einbetten hat nicht funktioniert(meine fehlende Python/Python-umgebungskenntnisse)

Aber ich kann jetzt trotzdem meine Scripter ausführen/debuggen.
Ich habe folgendes gemacht (doch IPC):
In Hauptprogramm :
TPythonEngine, TPythonModule und TIdTCPServer Komponenten genommen.

Code: Alles auswählen

//PythonModule.OnInitialization:
procedure TdmPython.pmCADSys4Initialization(Sender: TObject);
begin
  with Sender as TPythonModule do
  begin
    AddDelphiMethod('CAD_AddLine',   CAD_AddLine,    'CAD_AddLine');
  end;
end;
Die Methode ist natürlich implementiert und kann ganz normal auf Zeichnun zugreifen.
So schaut die Methode aus:

Code: Alles auswählen

function TdmPython.CAD_AddLine(pself, args : PPyObject ): PPyObject; cdecl;
var x0, y0, x1, y1: TRealType; colori: integer; layer: integer; TmpLine2D: TLine2D;
begin
  if PythonEngine1.PyArg_ParseTuple( args, 'ffffii:AddLine', @x0, @y0, @x1, @y1, @colori, @layer) <> 0 then
  begin
    TmpLine2D := TLine2D.Create(10, Point2D(x0, y0), Point2D(x1, y1));
    TmpLine2D.PenColor := colori;
    TmpLine2D.Layer    := layer;
    fCADCmp2D.AddObject(TmpLine2D.ID, TmpLine2D);
  end;
  Result := PythonEngine1.ReturnNone;
end;
In Hauptprogramm :
TIdTCPServer.OnExecute Ereignis:
(Diese Code ist von Delphi Treff, Indy Tutorials. Danke)

Code: Alles auswählen

// 'CADSys4'  ist PythonModule1.ModuleName.
procedure TdmPython.IdTCPServer1Execute(AContext: TIdContext);
var cmd: String;
begin
  try
    cmd := AContext.Connection.IOHandler.ReadLn;
    cmd := 'CADSys4.' + cmd;
    PythonEngine1.ExecString(UTF8Encode(cmd));
  finally
    //AContext.Connection.Disconnect;
  end;
end;
Und eine ganz einfache dll (CADSys4AppIntrf.dll) erstellt. Eine TIdTCPClient Komponente genommen.
So schaut die Bibliothek aus:

Code: Alles auswählen

library CADSys4AppIntrf;
{$mode delphi}{$H+}

uses
  Classes, SysUtils, Interfaces,  Dialogs,
  IdTCPClient, indylaz;

type
  TrealType = single;

var  IdTCPClient1: TIdTCPClient;

procedure CAD_AddLine(x0, y0, x1, y1: single; colori: integer; layer: integer); stdcall;
var cmd: string;
begin
  cmd := 'CAD_AddLine('
             + FloatToStr(x0)   + ', '
             + FloatToStr(y0)   + ', '
             + FloatToStr(x1)   + ', '
             + FloatToStr(y1)   + ', '
             + IntToStr(colori) + ', '
             + IntToStr(layer)  +
          ')';
  IdTCPClient1.IOHandler.WriteLn(cmd);
end;

exports
  CAD_AddLine;

initialization
  DefaultFormatSettings.DecimalSeparator := '.';
  try
    IdTCPClient1 := TIdTCPClient.Create(nil);
    IdTCPClient1.Host := '127.0.0.1';
    IdTCPClient1.Port := 40000;
    IdTCPClient1.Connect;
  except
    raise Exception.Create('can not connect to server!');
  end;

finalization
  IdTCPClient1.Disconnect;
  IdTCPClient1.Free;
end.
Und folgende Script erstellt:

Code: Alles auswählen

#Dieser Teil, kann man in einer Python-Datei schreiben und importieren.
#######################################################################
a = os.environ['path']
a =  os.getcwd() + ";" + a
os.environ['path'] = a
intrf = ct.windll.CADSys4AppIntrf

CAD_AddLine = intrf.CAD_AddLine
CAD_AddLine.restype = ct.c_int
CAD_AddLine.argtypes = [ct.c_float, ct.c_float, ct.c_float, ct.c_float, ct.c_int, ct.c_int]
############################################################################################

for i in range(0, 1800):
  x = i/100;
  y = math.sin(x);
  CAD_AddLine(x, y, x+2, y+2, 100, 0)
Und Thonny starte ich im Hauptprogramm so:

Code: Alles auswählen

procedure TfrmMainLinux.acToolsPythonIDEExecute(Sender: TObject);
var AProcess: TProcess; pgm: string;
begin
  try
    AProcess := TProcess.Create(self);
    {$IFDEF windows}
    pgm := applicationh.GetAppPath + 'libs\Python311-amd64\Scripts\thonny.exe';
    AProcess.Executable:= pgm;
    {$ENDIF}
    AProcess.Execute;
  finally
    AProcess.Free;
  end;
end;
Das ist alles.
Diese Lösung ist besser als Thonny einzubettten weil ich jetzt jeder IDE/Debugger verwenden kann,
welche eine DLL laden kann.
Diese Script habe ich mit Thonny und PyScripter ausgeführt. Funktioniert problemlos.
Wenn man IP-Adresse und Port in eine Ini-Datei schreibt, wird das Ganze sogar netzerktransparent.
( :-) ich weiss, in dem Fall, macht es keinen Sinn).

Und Ergebnis schaut so aus:
http://www.hackcad.com/maindownloads/python.mp4

Ich freue mich auf eure Kommentare und Verbesserungsvorschläge.
Danke,
Maurog.
Antworten