Python 4 Delphi Developers
Max Kleiner
Python-Delphi: Potential Synergies
Jupyter Notebook
Jupyter is a spin-off project from IPython, aiming to standardize interactive computing in any
programming languages. The kernel provides interactive environment that executes user code as a
server, connected with a frontend through sockets. A Jupyter Notebook is also an open-source web
application that allows you to create and share documents that contain live code, equations,
visualizations, and describing text.
Google Colab
With Colab you can import an image dataset, train an image classifier on it, and evaluate the model, all in
just a few lines of code. Colab notebooks execute code on Google’s cloud servers, meaning you can
leverage the power of Google hardware, including GPUs and TPUs, regardless of the power of your
machine.
TPU
Tensor Processing Unit (TPU) is an AI accelerator application-specific integrated circuit (ASIC) developed
by Google specifically for neural network machine learning, particularly using Google’s own TensorFlow
software.
Popularity of Python
https://www.tiobe.com/tiobe-index/
P4D is a set of free components that wrap up the
Python DLL into Delphi and Lazarus (FPC).
Python vs. Java
Interest over time (Google Trends)
Java
Python
Be yourself; Everyone else is already taken.
— Oscar Wilde.
Delphi vs Python
Delphi/Pascal Python
Maturity (1995/1970!) (1989)
Object orientation
Multi-platform
Verbosity High (begin end) Low (indentation based)
REPL No Yes
Typing Strong static typing Dynamic (duck) typing
Memory management Manual Reference counting
Compiled bytecode
Performance
Multi-threading
RAD
Python for Delphi (I)
Imagine you need a 512bit hash (or another master of reality procedure) and you don’t have the available function.
eng:= TPythonEngine.Create(Nil);
eng.pythonhome:= PYHOME;
eng.opendll(PYDLL)
//eng.IO:= pyMemo;
try
eng.Execstring('with open(r"'+exepath+'maXbox4.exe","rb") as afile:'+
' fbuf = afile.read()');
println(eng.evalstr('__import__("hashlib").sha512('+
'fbuf).hexdigest().upper()'));
except
eng.raiseError;
finally
eng.Free;
end;
https://maxbox4.wordpress.com/2021/09/03/ekon-25-pypas/
Python for Delphi (I)
Imagine you need a 512bit hash (or another master of reality procedure).
https://maxbox4.wordpress.com/2021/07/28/python4maxbox-code/
● The eval() method parses the expression passed to it and runs python
expression(code) within the program.
● Exec() expects a statement, doesn’t return any value; import or assignment is a
statement with exec().
The eval() is not just limited to simple expression. We can execute functions, call methods,
reference variables and so on. So we use this by using the __import__() built-in function.
Note also that the computed hash is converted to a readable hexadecimal string by
hexdigest().upper()’ and uppercase the hex-values in one line, amazing isn’t it.
Python for Delphi (II)
•
Delphi version support
• 2009 or later (Unicode free also < D2009)
•
Platform support
• Windows 32 & 64 bits
• Linux
• MacOS
•
Mostly non-visual components
• Can be used in console applications
•
Lazarus/FPC/maXbox support
Getting Started – Installing Python
•
Select a Python distribution
• www.python.org (official distribution)
• Anaconda (recommended for heavy data-analytics work)
•
Python 2 vs. Python 3
•
32-bits vs. 64-bits
•
Download and run the installer
•
Installation options (location, for all users)
•
Install python packages you are planning to use (can be done later)
• Use the python package installer (pip) from the command prompt
• eg. > pip install numpy
Getting Started – Installing Python
for Delphi
•
Clone or download and unzip the Github repository into a directory (e.g.,
D:ComponentsP4D).
•
Start RAD Studio or maXbox4.
•
Add the source subdirectory (e.g., D:ComponentsP4DSource) to the IDE's library
path for the targets you are planning to use.
•
Open and install the Python4Delphi package specific to the IDE being used. For
Delphi Sydney and later it can be found in the PackagesDelphiDelphi 10.4+
directory. For earlier versions use the package in the PackagesDelphiDelphi 10.3-
directory.
Note:  The package is Design & Runtime together
P4D Primer Demo
http://www.softwareschule.ch/examples/cheatsheetpython.pdf
Start with a Cheatsheet:
http://www.softwareschule.ch/examples/pydemo13.txt
and a Script:
with an Engine:
https://sourceforge.net/projects/maxbox/
SIMPLE DEMO
(I)
SynEdit
Memo
SIMPLE
DEMOTIVATION
(II)
•
All components are using default properties
• PythonGUIInputOutput linked to PythonEngine and
Memo in maXbox
•
Source Code:
procedure TForm1.btnRunClick(Sender: TObject);
begin
GetPythonEngine.ExecString(UTF8Encode(sePythonC
ode.Text));
end;
http://www.softwareschule.ch/examples/pydemo29.txt
Using TPythonModule (I)
Python
def is_prime(n):
""" totally naive implementation """
if n <= 1:
return False
q = math.floor(math.sqrt(n))
for i in range(2, q + 1):
if (n % i == 0):
return False
return True
Delphi
function IsPrime(x: Integer): Boolean;
begin
if (x <= 1) then Exit(False);
var q := Floor(Sqrt(x));
for var i := 2 to q do
if (x mod i = 0) then
Exit(False);
Exit(True);
end;
Python
def count_primes(max_n):
res = 0
for i in range(2, max_n + 1):
if is_prime(i):
res += 1
return res
def test():
max_n = 1000000
print(f'Number of primes between 0 and {max_n} = {count_primes(max_n)}')
def main():
print(f'Elapsed time: {Timer(stmt=test).timeit(1)} secs')
if __name__ == '__main__':
main()
Using TPythonModule (II)
Output
Number of primes between 0 and 1000000 = 78498
Elapsed time: 3.4528134000000037 secs
Python
from delphi_module import delphi_is_prime
def count_primes(max_n):
res = 0
for i in range(2, max_n + 1):
if delphi_is_prime(i):
res += 1
return res
Using TPMod. & Threads
(III)
eng.Execstring('t1 =
threading.Thread(target=print_hello_three_times)');
eng.Execstring('t2 =
threading.Thread(target=print_hi_three_times)');
eng.EvalStr('t1.start()');
eng.EvalStr('t2.start()');
Master with 2 workers!
println('thread target1: '+eng.EvalStr('t1'));
println('thread target2: '+eng.EvalStr('t2'));
http://www.softwareschule.ch/examples/pydemo26.txt
const TH2 = 'def print_hi_three_times():'+LB+
' for i in range(3): '+LB+
' print("a") '+LB+
' winsound.Beep(440, 500) '+LB+
' return "Hi"';
Output
Number of primes between 0 and 1000000 = 78498
Elapsed time: 0.3073742000000017 secs
10x + improvement!
Defs in P4D (IV)
•
Add a Def() named convert as a const and link it to the PythonEngine
– ModuleName: http://www.softwareschule.ch/examples/pydemo25.txt
– Import the module with ExecStr()
• Implement python function hexconvert by writing a Pascal call
HEXCONVERT =
'""" convert hex string integer to int """ '+LF+
'def convert(n: str) -> int: '+LF+
' # get rid of ":", spaces and newlines '+LF+
' hex = n.replace(":", "").replace("n","").replace(" ","")'+LF+
' return int(hex,16)';
Using PyTemplate (V)
•
Minimal Shell Configuration:
with TPythonEngine.Create(Nil) do begin
pythonhome:= PYHOME;
try
loadDLL;
Println('Decimal: '+
EvalStr('__import__("decimal").Decimal(0.1)'));
except
raiseError;
finally
free;
end;
end;
Using PYDelphiWrapper (VI)
•
PyDelphiWrapper allows you to expose Delphi objects, records and types using
RTTI and cusomised wrapping of common Delphi objects.
•
Add a TPyDelphiWrapper on the form and link it to a PythonModule.
•
You can wrap a Delphi record containing a class function.
type
TDelphiFunctions = record
class function count_primes(MaxN: integer): integer; static;
end;
var
DelphiFunctions: TDelphiFunctions;
procedure TForm1.FormCreate(Sender: TObject);
begin
var Py := PyDelphiWrapper.WrapRecord(@DelphiFunctions,
TRttiContext.Create.GetType(TypeInfo(TDelphiFunctions))
as TRttiStructuredType);
PythonModule.SetVar('delphi_functions', Py);
PythonEngine.Py_DecRef(Py);
end;
Conclusions
•
With Python for Delphi you can get the best of both worlds
•
P4D makes it possible to integrate Python into Delphi applications in RAD way
•
Expose Delphi function, objects, records and types to Python using low or high-level
interfaces
•
More interesting topics
• Using python libraries and objects in Delphi code like variants (VarPyth)
• Python based data analytics in Delphi applications for example TensorFlow or Pandas
Creating Python extension modules using Delphi (from delphi_module import
delphi_is_prime)
• Python GUI development using the VCL
Resources & Sources
●
Python4Delphi library
– https://github.com/pyscripter/python4delphi
●
PyScripter IDE
– https://github.com/pyscripter/pyscripter
●
Thinking in CS – Python3 Tutorial
– https://openbookproject.net/thinkcs/python/english3e/
●
Delphi Scripter maXbox
●
https://sourceforge.net/projects/maxbox/
●
Webinar blog post
– https://blogs.embarcadero.com/python-for-delphi-developers-webinar/
Based on a Webinar by Kiriakos
Vlahos (aka PyScripter)
& Jim McKeeth (Embarcadero)

Ekon 25 Python4Delphi_MX475

  • 1.
    Python 4 DelphiDevelopers Max Kleiner
  • 2.
    Python-Delphi: Potential Synergies JupyterNotebook Jupyter is a spin-off project from IPython, aiming to standardize interactive computing in any programming languages. The kernel provides interactive environment that executes user code as a server, connected with a frontend through sockets. A Jupyter Notebook is also an open-source web application that allows you to create and share documents that contain live code, equations, visualizations, and describing text. Google Colab With Colab you can import an image dataset, train an image classifier on it, and evaluate the model, all in just a few lines of code. Colab notebooks execute code on Google’s cloud servers, meaning you can leverage the power of Google hardware, including GPUs and TPUs, regardless of the power of your machine. TPU Tensor Processing Unit (TPU) is an AI accelerator application-specific integrated circuit (ASIC) developed by Google specifically for neural network machine learning, particularly using Google’s own TensorFlow software.
  • 3.
    Popularity of Python https://www.tiobe.com/tiobe-index/ P4Dis a set of free components that wrap up the Python DLL into Delphi and Lazarus (FPC).
  • 4.
    Python vs. Java Interestover time (Google Trends) Java Python Be yourself; Everyone else is already taken. — Oscar Wilde.
  • 5.
    Delphi vs Python Delphi/PascalPython Maturity (1995/1970!) (1989) Object orientation Multi-platform Verbosity High (begin end) Low (indentation based) REPL No Yes Typing Strong static typing Dynamic (duck) typing Memory management Manual Reference counting Compiled bytecode Performance Multi-threading RAD
  • 6.
    Python for Delphi(I) Imagine you need a 512bit hash (or another master of reality procedure) and you don’t have the available function. eng:= TPythonEngine.Create(Nil); eng.pythonhome:= PYHOME; eng.opendll(PYDLL) //eng.IO:= pyMemo; try eng.Execstring('with open(r"'+exepath+'maXbox4.exe","rb") as afile:'+ ' fbuf = afile.read()'); println(eng.evalstr('__import__("hashlib").sha512('+ 'fbuf).hexdigest().upper()')); except eng.raiseError; finally eng.Free; end; https://maxbox4.wordpress.com/2021/09/03/ekon-25-pypas/
  • 7.
    Python for Delphi(I) Imagine you need a 512bit hash (or another master of reality procedure). https://maxbox4.wordpress.com/2021/07/28/python4maxbox-code/ ● The eval() method parses the expression passed to it and runs python expression(code) within the program. ● Exec() expects a statement, doesn’t return any value; import or assignment is a statement with exec(). The eval() is not just limited to simple expression. We can execute functions, call methods, reference variables and so on. So we use this by using the __import__() built-in function. Note also that the computed hash is converted to a readable hexadecimal string by hexdigest().upper()’ and uppercase the hex-values in one line, amazing isn’t it.
  • 8.
    Python for Delphi(II) • Delphi version support • 2009 or later (Unicode free also < D2009) • Platform support • Windows 32 & 64 bits • Linux • MacOS • Mostly non-visual components • Can be used in console applications • Lazarus/FPC/maXbox support
  • 9.
    Getting Started –Installing Python • Select a Python distribution • www.python.org (official distribution) • Anaconda (recommended for heavy data-analytics work) • Python 2 vs. Python 3 • 32-bits vs. 64-bits • Download and run the installer • Installation options (location, for all users) • Install python packages you are planning to use (can be done later) • Use the python package installer (pip) from the command prompt • eg. > pip install numpy
  • 10.
    Getting Started –Installing Python for Delphi • Clone or download and unzip the Github repository into a directory (e.g., D:ComponentsP4D). • Start RAD Studio or maXbox4. • Add the source subdirectory (e.g., D:ComponentsP4DSource) to the IDE's library path for the targets you are planning to use. • Open and install the Python4Delphi package specific to the IDE being used. For Delphi Sydney and later it can be found in the PackagesDelphiDelphi 10.4+ directory. For earlier versions use the package in the PackagesDelphiDelphi 10.3- directory. Note:  The package is Design & Runtime together
  • 11.
    P4D Primer Demo http://www.softwareschule.ch/examples/cheatsheetpython.pdf Startwith a Cheatsheet: http://www.softwareschule.ch/examples/pydemo13.txt and a Script: with an Engine: https://sourceforge.net/projects/maxbox/
  • 12.
  • 13.
    SIMPLE DEMOTIVATION (II) • All components areusing default properties • PythonGUIInputOutput linked to PythonEngine and Memo in maXbox • Source Code: procedure TForm1.btnRunClick(Sender: TObject); begin GetPythonEngine.ExecString(UTF8Encode(sePythonC ode.Text)); end; http://www.softwareschule.ch/examples/pydemo29.txt
  • 14.
    Using TPythonModule (I) Python defis_prime(n): """ totally naive implementation """ if n <= 1: return False q = math.floor(math.sqrt(n)) for i in range(2, q + 1): if (n % i == 0): return False return True Delphi function IsPrime(x: Integer): Boolean; begin if (x <= 1) then Exit(False); var q := Floor(Sqrt(x)); for var i := 2 to q do if (x mod i = 0) then Exit(False); Exit(True); end;
  • 15.
    Python def count_primes(max_n): res =0 for i in range(2, max_n + 1): if is_prime(i): res += 1 return res def test(): max_n = 1000000 print(f'Number of primes between 0 and {max_n} = {count_primes(max_n)}') def main(): print(f'Elapsed time: {Timer(stmt=test).timeit(1)} secs') if __name__ == '__main__': main() Using TPythonModule (II) Output Number of primes between 0 and 1000000 = 78498 Elapsed time: 3.4528134000000037 secs
  • 16.
    Python from delphi_module importdelphi_is_prime def count_primes(max_n): res = 0 for i in range(2, max_n + 1): if delphi_is_prime(i): res += 1 return res Using TPMod. & Threads (III) eng.Execstring('t1 = threading.Thread(target=print_hello_three_times)'); eng.Execstring('t2 = threading.Thread(target=print_hi_three_times)'); eng.EvalStr('t1.start()'); eng.EvalStr('t2.start()'); Master with 2 workers! println('thread target1: '+eng.EvalStr('t1')); println('thread target2: '+eng.EvalStr('t2')); http://www.softwareschule.ch/examples/pydemo26.txt const TH2 = 'def print_hi_three_times():'+LB+ ' for i in range(3): '+LB+ ' print("a") '+LB+ ' winsound.Beep(440, 500) '+LB+ ' return "Hi"'; Output Number of primes between 0 and 1000000 = 78498 Elapsed time: 0.3073742000000017 secs 10x + improvement!
  • 17.
    Defs in P4D(IV) • Add a Def() named convert as a const and link it to the PythonEngine – ModuleName: http://www.softwareschule.ch/examples/pydemo25.txt – Import the module with ExecStr() • Implement python function hexconvert by writing a Pascal call HEXCONVERT = '""" convert hex string integer to int """ '+LF+ 'def convert(n: str) -> int: '+LF+ ' # get rid of ":", spaces and newlines '+LF+ ' hex = n.replace(":", "").replace("n","").replace(" ","")'+LF+ ' return int(hex,16)';
  • 18.
    Using PyTemplate (V) • MinimalShell Configuration: with TPythonEngine.Create(Nil) do begin pythonhome:= PYHOME; try loadDLL; Println('Decimal: '+ EvalStr('__import__("decimal").Decimal(0.1)')); except raiseError; finally free; end; end;
  • 19.
    Using PYDelphiWrapper (VI) • PyDelphiWrapperallows you to expose Delphi objects, records and types using RTTI and cusomised wrapping of common Delphi objects. • Add a TPyDelphiWrapper on the form and link it to a PythonModule. • You can wrap a Delphi record containing a class function. type TDelphiFunctions = record class function count_primes(MaxN: integer): integer; static; end; var DelphiFunctions: TDelphiFunctions; procedure TForm1.FormCreate(Sender: TObject); begin var Py := PyDelphiWrapper.WrapRecord(@DelphiFunctions, TRttiContext.Create.GetType(TypeInfo(TDelphiFunctions)) as TRttiStructuredType); PythonModule.SetVar('delphi_functions', Py); PythonEngine.Py_DecRef(Py); end;
  • 20.
    Conclusions • With Python forDelphi you can get the best of both worlds • P4D makes it possible to integrate Python into Delphi applications in RAD way • Expose Delphi function, objects, records and types to Python using low or high-level interfaces • More interesting topics • Using python libraries and objects in Delphi code like variants (VarPyth) • Python based data analytics in Delphi applications for example TensorFlow or Pandas Creating Python extension modules using Delphi (from delphi_module import delphi_is_prime) • Python GUI development using the VCL
  • 21.
    Resources & Sources ● Python4Delphilibrary – https://github.com/pyscripter/python4delphi ● PyScripter IDE – https://github.com/pyscripter/pyscripter ● Thinking in CS – Python3 Tutorial – https://openbookproject.net/thinkcs/python/english3e/ ● Delphi Scripter maXbox ● https://sourceforge.net/projects/maxbox/ ● Webinar blog post – https://blogs.embarcadero.com/python-for-delphi-developers-webinar/ Based on a Webinar by Kiriakos Vlahos (aka PyScripter) & Jim McKeeth (Embarcadero)