Using Python in Lazarus on Windows/Linux: what changed
Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.
Title: Using Python in Lazarus on Windows/Linux
| Old | New | Line | |
|---|---|---|---|
| 1 | + | # Intro | |
| 2 | + | ||
| 3 | + | I needed to make an app, cross platform, for Windows/Linux/Mac, which embeds Python engine. I tried [[Python4Delphi]], it didn't compile and work on Linux x64 and Mac. App must use portable Python on Windows, system Python on Linux/Mac. | |
| 4 | + | ||
| 5 | + | Update for [[Python4Delphi]]: [The commit from 21.1.2018 claims the compatibility with both Lazarus and (hopefully) Delphi Linux](https://github.com/pyscripter/python4delphi/commit/88c06f11e70d471fc5dfd3b1e7e446c09eb5ab9a) | |
| 6 | + | ||
| 7 | + | # Results | |
| 8 | + | ||
| 9 | + | Github repo: <https://github.com/Alexey-T/Python-for-Lazarus> | |
| 10 | + | ||
| 11 | + | It has demo, which shows TEdit+TMemo as Python console, to input commands in Edit and show results in Memo. Special allowed first char "=" means to do "print(...)". | |
| 12 | + | ||
| 13 | + | Screenshot on Ubuntu 14 x64: | |
| 14 | + | ||
| 15 | + |  | |
| 16 | + | ||
| 17 | + | Screenshot on Windows 7 x64: | |
| 18 | + | ||
| 19 | + |  | |
| 20 | + | ||
| 21 | + | Screenshot on macOS 10.8: | |
| 22 | + | ||
| 23 | + |  | |
| 24 | + | ||
| 25 | + | Repo was forked from Python4Delphi package. Compile and install the Lazarus package. You will see "Python" tab in IDE component palette. What is changed since original Python4Delphi: | |
| 26 | + | ||
| 27 | + | - deleted all refs to units "..Delphi..", seems units aren't needed for Lazarus apps. | |
| 28 | + | - modifications to PythonEngine.pas, see lines with "//AT". | |
| 29 | + | - added support for macOS, for ex by replacing "\$ifdef linux" with "\$ifdef unix". | |
| 30 | + | ||
| 31 | + | # Files on Windows | |
| 32 | + | ||
| 33 | + | On Windows you need to copy files to app folder. | |
| 34 | + | ||
| 35 | + | ## Python 3.3 | |
| 36 | + | ||
| 37 | + | From "Sublime Text 3" installation for Windows, take Python files: | |
| 38 | + | ||
| 39 | + | - python33.dll | |
| 40 | + | - msvcr100.dll | |
| 41 | + | - python33.zip | |
| 42 | + | - .pyd files, copy them to subfolder DLLs | |
| 43 | + | ||
| 44 | + | ## Python 3.5 or later | |
| 45 | + | ||
| 46 | + | You need files for another Python version: *.dll, *.pyd, python*.zip. Get them at official site Python.org: | |
| 47 | + | ||
| 48 | + | - "Windows x86 embeddable zip file" for 32-bit application | |
| 49 | + | - "Windows x86-64 embeddable zip file" for 64-bit application | |
| 50 | + | ||
| 51 | + | Also you must change Lazarus component property for your Python version: DllName and/or DllPath. See the demo program, how to set them. | |
| 52 | + | ||
| 53 | + | ``` pascal | |
| 54 | + | procedure TfmMain.DoPy_InitEngine; | |
| 55 | + | var | |
| 56 | + | S: string; | |
| 57 | + | begin | |
| 58 | + | S:= | |
| 59 | + | {$ifdef windows} cPyLibraryWindows {$endif} | |
| 60 | + | {$ifdef linux} cPyLibraryLinux {$endif} | |
| 61 | + | {$ifdef darwin} cPyLibraryMac {$endif} ; | |
| 62 | + | PythonEngine.DllPath:= ExtractFileDir(S); | |
| 63 | + | PythonEngine.DllName:= ExtractFileName(S); | |
| 64 | + | PythonEngine.LoadDll; | |
| 65 | + | end; | |
| 66 | + | ``` | |
| 67 | + | ||
| 68 | + | ## Manifest file | |
| 69 | + | ||
| 70 | + | Manifest file (for all Python versions) should be named like "appname.exe.manifest". | |
| 71 | + | ||
| 72 | + | ``` xml | |
| 73 | + | <?xml version="1.0" encoding="UTF-8" standalone="yes"?> | |
| 74 | + | <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> | |
| 75 | + | <noInheritable/> | |
| 76 | + | <assemblyIdentity | |
| 77 | + | type="win32" | |
| 78 | + | name="DelphiApplication" | |
| 79 | + | version="1.0.0.0" | |
| 80 | + | processorArchitecture="*"/> | |
| 81 | + | <dependency> | |
| 82 | + | <dependentAssembly> | |
| 83 | + | <assemblyIdentity type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*' /> | |
| 84 | + | </dependentAssembly> | |
| 85 | + | </dependency> | |
| 86 | + | <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3"> | |
| 87 | + | <security> | |
| 88 | + | <requestedPrivileges> | |
| 89 | + | <requestedExecutionLevel level='asInvoker' uiAccess='false' /> | |
| 90 | + | </requestedPrivileges> | |
| 91 | + | </security> | |
| 92 | + | </trustInfo> | |
| 93 | + | </assembly> | |
| 94 | + | ``` | |
| 95 | + | ||
| 96 | + | # Files on MacOS | |
| 97 | + | ||
| 98 | + | 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. | |
| 99 | + | ||
| 100 | + | 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). | |
| 101 | + | ||
| 102 | + | # Code | |
| 103 | + | ||
| 104 | + | ## Form | |
| 105 | + | ||
| 106 | + | Put on form: | |
| 107 | + | ||
| 108 | + | - TPythonEngine | |
| 109 | + | - TPythonInputOutput | |
| 110 | + | - TCombobox (edConsole) | |
| 111 | + | - TMemo (memoConsole) | |
| 112 | + | ||
| 113 | + | Properties of PythonEngine: | |
| 114 | + | ||
| 115 | + | - AutoLoad=False | |
| 116 | + | - DllName empty | |
| 117 | + | - DllPath empty | |
| 118 | + | - FatalAbort=False | |
| 119 | + | - InitScript="import sys; print('Python', sys.version)" | |
| 120 | + | - IO=PythonInputOutput1 | |
| 121 | + | - PyFlags=\[pfIgnoreEnvironmentFlag\] | |
| 122 | + | - UseLastKnownVersion=False | |
| 123 | + | ||
| 124 | + | ## Event handlers | |
| 125 | + | ||
| 126 | + | - PythonEngine.OnAfterInit: must set "sys.path" for Win (remember, we use portable py for Win). | |
| 127 | + | ||
| 128 | + | ``` pascal | |
| 129 | + | procedure TfmMain.PythonEngineAfterInit(Sender: TObject); | |
| 130 | + | var | |
| 131 | + | dir: string; | |
| 132 | + | begin | |
| 133 | + | {$ifdef windows} | |
| 134 | + | dir:= ExtractFilePath(Application.ExeName); | |
| 135 | + | Py_SetSysPath([ | |
| 136 | + | dir + 'DLLs', | |
| 137 | + | dir + 'python33.zip' | |
| 138 | + | ]); | |
| 139 | + | {$endif} | |
| 140 | + | end; | |
| 141 | + | ||
| 142 | + | procedure Py_SetSysPath(const Dirs: array of string); | |
| 143 | + | var | |
| 144 | + | Str: string; | |
| 145 | + | i: Integer; | |
| 146 | + | begin | |
| 147 | + | Str:= ''; | |
| 148 | + | for i:= 0 to Length(Dirs)-1 do | |
| 149 | + | Str:= Str + 'r"' + Dirs[i] + '"' + ','; | |
| 150 | + | Str:= Format('sys.path = [%s]', [Str]); | |
| 151 | + | GetPythonEngine.ExecString(Str); | |
| 152 | + | end; | |
| 153 | + | ``` | |
| 154 | + | ||
| 155 | + | - PythonInputOutput.OnSendData, OnSendUniData: | |
| 156 | + | ||
| 157 | + | ``` pascal | |
| 158 | + | procedure TfmMain.PythonInputOutput1SendData(Sender: TObject; | |
| 159 | + | const Data: AnsiString); | |
| 160 | + | begin | |
| 161 | + | memoConsole.Lines.Add(Data); | |
| 162 | + | end; | |
| 163 | + | ||
| 164 | + | procedure TfmMain.PythonInputOutput1SendUniData(Sender: TObject; | |
| 165 | + | const Data: UnicodeString); | |
| 166 | + | begin | |
| 167 | + | memoConsole.Lines.Add(Data); | |
| 168 | + | end; | |
| 169 | + | ``` | |
| 170 | + | ||
| 171 | + | - edConsole.OnKeyPress: | |
| 172 | + | ||
| 173 | + | ``` pascal | |
| 174 | + | procedure TfmMain.edConsoleKeyPress(Sender: TObject; var Key: char); | |
| 175 | + | var | |
| 176 | + | Str: string; | |
| 177 | + | begin | |
| 178 | + | if Key=#13 then | |
| 179 | + | begin | |
| 180 | + | Str:= edConsole.Text; | |
| 181 | + | ||
| 182 | + | //support entering "=some cmd" | |
| 183 | + | if (Str<>'') and (Str[1]='=') then | |
| 184 | + | Str:= 'print('+Copy(Str, 2, MaxInt) + ')'; | |
| 185 | + | ||
| 186 | + | memoConsole.Lines.Add('>>> '+Str); | |
| 187 | + | edConsole.Text:= ''; | |
| 188 | + | edConsole.Items.Insert(0, Str); | |
| 189 | + | try | |
| 190 | + | GetPythonEngine.ExecString(Str); | |
| 191 | + | except | |
| 192 | + | end; | |
| 193 | + | end; | |
| 194 | + | end; | |
| 195 | + | ``` | |
| 196 | + | ||
| 197 | + | - main form OnCreate: | |
| 198 | + | ||
| 199 | + | ``` pascal | |
| 200 | + | const | |
| 201 | + | cPyLibraryWindows = 'python33.dll'; | |
| 202 | + | cPyLibraryLinux = 'libpython3.4m.so.1.0'; | |
| 203 | + | cPyLibraryMac = '/Library/Frameworks/Python.framework/Versions/3.4/lib/libpython3.4.dylib'; | |
| 204 | + | ||
| 205 | + | procedure TfmMain.FormCreate(Sender: TObject); | |
| 206 | + | var | |
| 207 | + | S: string; | |
| 208 | + | begin | |
| 209 | + | S:= | |
| 210 | + | {$ifdef windows} cPyLibraryWindows {$endif} | |
| 211 | + | {$ifdef linux} cPyLibraryLinux {$endif} | |
| 212 | + | {$ifdef darwin} cPyLibraryMac {$endif} ; | |
| 213 | + | PythonEngine.DllPath:= ExtractFileDir(S); | |
| 214 | + | PythonEngine.DllName:= ExtractFileName(S); | |
| 215 | + | PythonEngine.LoadDll; | |
| 216 | + | end; | |
| 217 | + | ``` | |
| 218 | + | ||
| 219 | + | --- | |
| 220 | + | *From the Free Pascal wiki, page "Using Python in Lazarus on Windows/Linux", as it stood on 2020-03-04 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).* | |
| 221 | + | Category: Code Snippets | |
| 222 | + | Category: Linux | |
| 223 | + | Category: Other programming languages | |
| 224 | + | Category: Python | |
| 225 | + | Category: Windows |
