Using Python in Lazarus on Windows/Linux
From Free Pascal wiki
Intro
I need to make app, cross platform, Win/Linux, which embeds Python engine. I tried Python4Delphi, but it doesn't compile and work on Linux x64. Same app must run on Win and Linux, must use portable Python 3 on Win and system Python 3 on Linux.
Result
Links
Work on Ubuntu 14.04 x64
Work on Windows7 x64
Code
P4D
Package "p4dlaz.lpk": delete all refs to units "...Delphi...". (Maybe units aren't needed for Lazarus apps.) Make modifications to PythonEngine.pas, see lines with "//AT". Compile and use package. You must see "Python" tab appeared in component pallette.
Files
--
App form
Put on form: TPythonEngine, TPythonInputOutput, set such props of PythonEngine:
- AutoLoad=False
- DllName empty
- DllPath empty
- FatalAbort=False
- InitScript="import sys; print('Python', sys.version)"
- IO=PythonInputOutput1
- PyFlags=[pfIgnoreEnvironmentFlag]
- UseLastKnownVersion=False
Event handlers
- PythonEngine.OnAfterInit: must add paths to "sys.path". Must do only for Windows, for portable Python, don't do for Linux. I add paths: dir+'DLLs', dir+'python33.zip', dir+'Py' (dir is ExtractFilePath(Application.ExeName)).
procedure TfmMain.PythonEngineAfterInit(Sender: TObject); var SDir, S1, S2, S3: string; begin {$ifdef windows} SDir:= ExtractFilePath(Application.ExeName); S1:= SDir + 'DLLs'; S2:= SDir + 'python33.zip'; S3:= SDir + 'Py'; Py_SetSysPath([S1, S2, S3]); {$endif} end;
procedure Py_SetSysPath(const Dirs: array of string); var Str: AnsiString; i: Integer; begin Str:= ; for i:= 0 to Length(Dirs)-1 do Str:= Str + SWideStringToPythonString(Dirs[i]) + ','; Str:= Format('sys.path = [%s]', [Str]); GetPythonEngine.ExecString(Str); end;
- PythonInputOutput.OnSendData, OnSendUniData:
procedure TfmMain.PythonInputOutput1SendData(Sender: TObject; const Data: AnsiString); begin memoConsole.Lines.Add(Data); end;
procedure TfmMain.PythonInputOutput1SendUniData(Sender: TObject; const Data: UnicodeString); begin memoConsole.Lines.Add(Data); end;
- edConsole.OnKeyPress:
procedure TfmMain.edConsoleKeyPress(Sender: TObject; var Key: char); var Str: string; begin if Key=#13 then begin Str:= edConsole.Text; //support entering "=some cmd" if (Str<>) and (Str[1]='=') then Str:= 'print('+Copy(Str, 2, MaxInt) + ')'; memoConsole.Lines.Add('>>> '+Str); edConsole.Text:= ; edConsole.Items.Insert(0, Str); try GetPythonEngine.ExecString(Str); except end; end; end;
- main form OnCreate:
procedure TfmMain.FormCreate(Sender: TObject); begin {$ifdef windows} PythonEngine.DllName:= 'python33.dll'; {$endif} {$ifdef linux} PythonEngine.DllName:= 'libpython3.4m.so.1.0'; {$endif}
PythonEngine.LoadDll; end;