Difference between revisions of "Using Python in Lazarus on Windows/Linux/ru"

From Lazarus wiki
Jump to navigationJump to search
Line 30: Line 30:
 
* добалена поддержка macOS, наприме "$ifdef linux" заменён на "$ifdef unix".
 
* добалена поддержка macOS, наприме "$ifdef linux" заменён на "$ifdef unix".
  
= Files on Windows =
+
= Файлы для Windows =
  
On Windows you need to copy files to app folder.
+
В Windows нужно скопировать файлы в папку приложения.
  
 
==Python 3.3==
 
==Python 3.3==
From "Sublime Text 3" installation for Windows, take Python files:  
+
Из папки "Sublime Text 3" в пакете для Windows, возьмите файлы Python:  
  
 
* python33.dll
 
* python33.dll
 
* msvcr100.dll
 
* msvcr100.dll
 
* python33.zip
 
* python33.zip
* .pyd files, copy them to subfolder DLLs
+
* .pyd files, скопируйте их в подпапку DLLs
  
==Python 3.5 or later==
+
==Python 3.5 или новее==
You need files for another Python version: *.dll, *.pyd, python*.zip. Get them at official site Python.org:
+
Вам нужны файлы для другой версии Python: *.dll, *.pyd, python*.zip. Возьмите их на официальном сайте Python.org:
  
* "Windows x86 embeddable zip file" for 32-bit application
+
* "Windows x86 embeddable zip file" для 32-разрядного приложения
* "Windows x86-64 embeddable zip file" for 64-bit application
+
* "Windows x86-64 embeddable zip file" для 64-разрядного приложения
  
Also you must change Lazarus component property for your Python version: DllName and/or DllPath. See the demo program, how to set them.
+
Также вам надо заменить свойство компонента для Lazarus на вашу версию Python: DllName и/или DllPath. Смотрите в демонстрационной программе как их задать.
  
 
<syntaxhighlight lang=pascal>
 
<syntaxhighlight lang=pascal>
Line 65: Line 65:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
==Manifest file==
+
== Файл манифеста ==
Manifest file (for all Python versions) should be named like "appname.exe.manifest".
+
Файл манифеста во всех версиях Python должен называться "appname.exe.manifest".
  
 
<syntaxhighlight lang="xml">
 
<syntaxhighlight lang="xml">

Revision as of 15:10, 2 June 2023

Введение

Мне нужно было сделать кроссплатформенное приложение для Windows/Linux/Mac, в которое встроен движок Python. Я попробовал Python4Delphi, но он не компилировался и не работал на Linux x64 и Mac. Приложение должно использовать portable Python в Windows и встроенный Python в Linux/Mac.

Обновлено Python4Delphi: Коммит от 21.1.2018 объявляет совместимость с Lazarus и (я надеюсь) Delphi Linux

Результаты

Репозиторий Github: https://github.com/Alexey-T/Python-for-Lazarus

Имеется демо, которое показывает TEdit+TMemo в консоли Python, чтобы вводить команды в Edit и показывать результаты в Memo. Специальный символ "=" в начале текста означает выполнение "print(...)".

Скриншот на Ubuntu 14 x64:

Python app Linux.png

Скриншот на Windows 7 x64:

Python app Windows.png

Скриншот на macOS 10.8:

Python app MacOS.png

Репозиторий создан на базе пакета Python4Delphi. Компилируется и устанавливается как пакет Lazarus. Вы увидите вкладку "Python" в палитре компонентов IDE. В чём отличия от оригинального Python4Delphi:

  • удалены все ссылки на модули, содержащие в имени "..Delphi..", кажется они не нужны приложениям Lazarus.
  • изменения в PythonEngine.pas, смотрите строки, начинающиеся с "//AT".
  • добалена поддержка macOS, наприме "$ifdef linux" заменён на "$ifdef unix".

Файлы для Windows

В Windows нужно скопировать файлы в папку приложения.

Python 3.3

Из папки "Sublime Text 3" в пакете для Windows, возьмите файлы Python:

  • python33.dll
  • msvcr100.dll
  • python33.zip
  • .pyd files, скопируйте их в подпапку DLLs

Python 3.5 или новее

Вам нужны файлы для другой версии Python: *.dll, *.pyd, python*.zip. Возьмите их на официальном сайте Python.org:

  • "Windows x86 embeddable zip file" для 32-разрядного приложения
  • "Windows x86-64 embeddable zip file" для 64-разрядного приложения

Также вам надо заменить свойство компонента для Lazarus на вашу версию Python: DllName и/или DllPath. Смотрите в демонстрационной программе как их задать.

procedure TfmMain.DoPy_InitEngine;
var
  S: string;
begin
  S:=
    {$ifdef windows} cPyLibraryWindows {$endif}
    {$ifdef linux} cPyLibraryLinux {$endif}
    {$ifdef darwin} cPyLibraryMac {$endif} ;
  PythonEngine.DllPath:= ExtractFileDir(S);
  PythonEngine.DllName:= ExtractFileName(S);
  PythonEngine.LoadDll;
end;

Файл манифеста

Файл манифеста во всех версиях Python должен называться "appname.exe.manifest".

  <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
    <noInheritable/>
    <assemblyIdentity
        type="win32"
        name="DelphiApplication"
        version="1.0.0.0" 
        processorArchitecture="*"/>
    <dependency>
      <dependentAssembly>
        <assemblyIdentity type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*' />
      </dependentAssembly>
    </dependency>
    <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
      <security>
        <requestedPrivileges>
          <requestedExecutionLevel level='asInvoker' uiAccess='false' />
        </requestedPrivileges>
      </security>
    </trustInfo>
  </assembly>

Files on MacOS

macOS doesn't have preinstalled Python. User needs to install Python 3 package (demo must work with Py 3.4) from official www.python.org.

Then full path to Python library must be set in program code. It is easy to set this path, it is always the standard path like "/Library/Frameworks/Python.framework/Versions/3.5/lib/libpython3.5.dylib" (with different numbers 3.x).

Code

Form

Put on form:

  • TPythonEngine
  • TPythonInputOutput
  • TCombobox (edConsole)
  • TMemo (memoConsole)

Properties 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 set "sys.path" for Win (remember, we use portable py for Win).
procedure TfmMain.PythonEngineAfterInit(Sender: TObject);
var
  dir: string;
begin
  {$ifdef windows}
  dir:= ExtractFilePath(Application.ExeName);
  Py_SetSysPath([
    dir + 'DLLs',
    dir + 'python33.zip'
    ]);
  {$endif}
end;

procedure Py_SetSysPath(const Dirs: array of string);
var
  Str: string;
  i: Integer;
begin
  Str:= '';
  for i:= 0 to Length(Dirs)-1 do
    Str:= Str + 'r"' + 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:
const
  cPyLibraryWindows = 'python33.dll';
  cPyLibraryLinux = 'libpython3.4m.so.1.0';
  cPyLibraryMac = '/Library/Frameworks/Python.framework/Versions/3.4/lib/libpython3.4.dylib';

procedure TfmMain.FormCreate(Sender: TObject);
var
  S: string;
begin
  S:=
    {$ifdef windows} cPyLibraryWindows {$endif}
    {$ifdef linux} cPyLibraryLinux {$endif}
    {$ifdef darwin} cPyLibraryMac {$endif} ;
  PythonEngine.DllPath:= ExtractFileDir(S);
  PythonEngine.DllName:= ExtractFileName(S);
  PythonEngine.LoadDll;
end;