下载地址:https://github.com/pyscripter/python4delphi
下载或者克隆P4D到指定的目录,例如:MDS_New,目录结构如下,P4D就是克隆下来的控件全部目录。
首先关闭正在运行的Delphi IDE!
在下载的目录Install(MDS_New\P4D\Install)中,点击 MultiInstaller.exe 进行安装。
提示:
在安装目录中的Setup.ini中默认定义了安装的目录是在P4D目录下,这一步体现在2.1.2选择的目录之下。例如:2.1.2步骤中选择 D:\MDS_New 则试剂安装在 D:\MDS_New\P4D目录中,如果需要更改这个目录,则需要修改Setup.ini文件。
强烈建议不要修改,这个安装程序是有问题的,默认安装才可以!
[Package - Python4Delphi] Name=Python4Delphi Folder=P4D SearchPath="Source"
注意:
勾选 Compile packages and install on IDE 选项,这样就会安装完成后,在控件面板上显示已经安装好的P4D控件。
另外注意,这里选择目录是上一级目录,实际默认安装在这一级目录下的P4D目录中。
自动安装和手动安装是完全独立的安装方式,但只需要成功执行一次就可以。对于手动安装,比如已经将P4D克隆到了 D:\MDS_New\P4D 目录中。
对于10.4+以上版本就选择10.4+,否则选择10.3-。 选择 Build All
打开Delphi 12,不同的Delphi版本都是可以的,从10.4开始,都是一样的,10.3以下的版本有区别。
如果看到控件面板上包含P4D的控件,这样就算安装成功了!
由于P4D是使用Python和Delphi两种语言,那么正常理解,Python的环境是必须要安装的,但事实上,完整安装了Python的环境当然是没有问题的,但是,如果我们给客户开发了一个软件,还需要开户安装Python开发环境,这就太奢侈了,所以也还有个不需要完整安装Python开发环境的路。
对于完整安装,本文就不多说,对于只需要一个极简安装环境的,说明如下,其实Python的运行环境就是一个DLL和一些lib库,只要这两个有了,就可以运行起来了。
以pythpon38为例:
这个DLLs是如果有Python代码引用到三方的DLL,那么三方的DLL就在这个目录中,如果没有引用到,就可以不需要这个目录。特别注意X32和X64是不同的版本,32位的Python就只能用32位的Delphi,必须对应使用。
做一个Delphi 的程序,然后在写Python代码,就可以尝试运行了,举例:
unit uMainForm;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.Buttons,
Vcl.Samples.Spin, Vcl.ExtCtrls,
system.Math,
System.Threading,
System.DateUtils, PythonEngine, Vcl.PythonGUIInputOutput,
VarPyth;
//PythonEngine, Vcl.PythonGUIInputOutput;
type
TForm1 = class(TForm)
Splitter1: TSplitter;
Panel1: TPanel;
Memo1: TMemo;
SpeedButton1: TSpeedButton;
PythonGUIInputOutput1: TPythonGUIInputOutput;
PythonEngine1: TPythonEngine;
SpeedButton2: TSpeedButton;
PythonModule1: TPythonModule;
SpeedButton_LoadDLL: TSpeedButton;
OpenDialog1: TOpenDialog;
Edit1: TEdit;
SpeedButton_UnLoadDLL: TSpeedButton;
SpeedButton3: TSpeedButton;
Memo2: TMemo;
procedure PythonEngine1BeforeLoad(Sender: TObject);
procedure SpeedButton1Click(Sender: TObject);
procedure SpeedButton2Click(Sender: TObject);
procedure PythonModule1Events0Execute(Sender: TObject; PSelf,
Args: PPyObject; var Result: PPyObject);
procedure SpeedButton_LoadDLLClick(Sender: TObject);
procedure SpeedButton_UnLoadDLLClick(Sender: TObject);
procedure FormResize(Sender: TObject);
procedure PythonModule1Events1Execute(Sender: TObject; PSelf,
Args: PPyObject; var Result: PPyObject);
procedure SpeedButton3Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
function IsPrime(n : integer) : Boolean;
function CountPrimes(MaxN : Integer) : Integer;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
{ TForm1 }
function TForm1.CountPrimes(MaxN: Integer): Integer;
var
Count : integer;
begin
TParallel.For(2,MaxN,procedure(i: integer)
begin
if IsPrime(i) then
AtomicIncrement(Count);
end);
Result := Count;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
{$IFDEF WIN32}
{$IFDEF DEBUG}
Self.Caption := 'P4D Demo示例 ( Win32 ) Debug';
{$ELSE}
Self.Caption := 'P4D Demo示例 ( Win32 ) Release';
{$ENDIF}
{$ELSE}
{$IFDEF DEBUG}
Self.Caption := 'P4D Demo示例 ( Win64 ) Debug';
{$ELSE}
Self.Caption := 'P4D Demo示例 ( Win64 ) Release';
{$ENDIF}
{$ENDIF}
end;
procedure TForm1.FormResize(Sender: TObject);
begin
//
Memo2.Height := Trunc((Self.ClientHeight - Panel1.Height) * 0.7);
end;
function TForm1.IsPrime(n: integer): Boolean;
begin
if n <= 1 then Exit(False);
var q := Floor(Sqrt(n));
for var i := 2 to q do
if (n mod i = 0) then Exit(False);
Exit(True);
end;
procedure TForm1.PythonEngine1BeforeLoad(Sender: TObject);
begin
//PythonEngine1.SetPythonHome(PythonEngine1.DllPath); //必须设置这一步
end;
procedure TForm1.PythonModule1Events0Execute(Sender: TObject; PSelf,
Args: PPyObject; var Result: PPyObject);
var
N : integer;
begin
with GetPythonEngine do
if PyArg_ParseTuple(Args,'i:delphi_is_prime',@N) <> 0 then
begin
if IsPrime(N) then
Result := PPyObject(Py_True)
else
Result := PPyObject(Py_False);
Py_INCREF(Result);
end
else
Result := nil;
end;
procedure TForm1.PythonModule1Events1Execute(Sender: TObject; PSelf,
Args: PPyObject; var Result: PPyObject);
var
N : integer;
begin
with GetPythonEngine do
if PyArg_ParseTuple(Args,'i:delphi_count_primes',@N) <> 0 then
begin
Result := PyLong_FromLong(CountPrimes(N));
Py_INCREF(Result);
end
else
Result := nil;
end;
procedure TForm1.SpeedButton1Click(Sender: TObject);
begin
if not PythonEngine1.Initialized then
begin
Memo1.Lines.Add('请先装载Python DLL');
Exit;
end;
//GetPythonEngine.ExecStrings(SynEdit1.Lines);
PythonEngine1.ExecStrings(Memo2.Lines);
end;
procedure TForm1.SpeedButton2Click(Sender: TObject);
var
aTask: ITask;
T : TDateTime;
path : string;
PyModule: Variant;
begin
if not PythonEngine1.Initialized then
begin
Memo1.Lines.Add('请先装载Python DLL');
Exit;
end;
aTask := TTask.Create(
procedure
begin
T := Now;
TThread.Synchronize(TThread.Current,
procedure
begin
Memo1.Lines.add('线程运行开始时间: ' + FormatDateTime('hh:mm:ss zzz',T));
end);
PythonEngine1.ExecStrings(Memo2.Lines);
// path := 'D:\MDS_New\Demo\camera';
// PyModule := SysModule;
// PyModule.path.append(path);
// PyModule := Import('run');
// PyModule.start();
TThread.Synchronize(TThread.Current,
procedure
begin
Memo1.Lines.add('线程运行结束时间: ' + FormatDateTime('hh:mm:ss zzz',Now) + #13#10'线程执行花费时长: ' + (MilliSecondsBetween(Now,T) / 1000).ToString + ' 秒');
end);
end);
aTask.Start;
end;
procedure TForm1.SpeedButton3Click(Sender: TObject);
var
PyModule: Variant;
path : string;
begin
{
path := 'D:\MDS_New\Demo\camera';
PyModule := SysModule;
PyModule.path.append(path);
PyModule := Import('run');
PyModule.start();
}
//PyModule := Import('hello');
//PyModule.SayHello('ABC 你好吗');
end;
procedure TForm1.SpeedButton_LoadDLLClick(Sender: TObject);
begin
if not OpenDialog1.Execute then Exit;
Edit1.Text := OpenDialog1.FileName;
//进行运行环境装载
PythonEngine1.DllPath := ExtractFilePath(OpenDialog1.FileName);// 'Y:\Documents\sensorwu\Python4Delphi\x86py38';
PythonEngine1.DllName := ExtractFileName(OpenDialog1.FileName);
PythonEngine1.SetPythonHome(PythonEngine1.DllPath); //必须设置这一步
PythonEngine1.LoadDll;
SpeedButton_LoadDLL.Enabled := False;
SpeedButton_UnLoadDLL.Enabled := True;
end;
procedure TForm1.SpeedButton_UnLoadDLLClick(Sender: TObject);
begin
PythonEngine1.UnloadDll;
SpeedButton_LoadDLL.Enabled := True;
SpeedButton_UnLoadDLL.Enabled := False;
end;
end.
#-------------------------------------------------------------------------------
# Name: module1
# Purpose: 判断素数测试
#
# Author: wuxihong
#
# Created: 01-02-2024
# Copyright: (c) wuxihong 2024
# Licence:
#-------------------------------------------------------------------------------
#-------- 以下这个包是从delphi 中导入的,打开该引用,同时打开下面的delphi_is_prime实现调用Delphi函数 -------
# ---------- delphi_count_primes 完全使用Delphi的并行计算,速度提高非常多
#from delphi_module import delphi_is_prime
#from delphi_module import delphi_count_primes
#-------------------------------------------
import math
from timeit import Timer
def is_prime(n):
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
def count_primes(max_n):
res = 0
for i in range(2,max_n + 1):
#----------- 以下这句是引用 Delphi 包中的函数 delphi_is_prime,打开该语句,屏蔽下面一句 if
#if delphi_is_prime(i):
#-------------------------------------
if is_prime(i):
res += 1
return res
def test():
max_n = 100000
print(f'Number of primes between 0 and {max_n} = {count_primes(max_n)}')
#----------- 以下这句是引用 Delphi 包中的函数 delphi_count_primes,打开该语句,屏蔽上面一句,即可体会到Delphi的并行运算能力
#print(f'Number of primes between 0 and {max_n} = {delphi_count_primes(max_n)}')
def main():
print(f'Elapsed Time: {Timer(stmt=test).timeit(1)} secs')
if __name__ == '__main__':
main()
这是一个计算素数个数的演示程序,可以完全通过Python来计算,也可以在Python中调用Delphi的函数来计算,演示了如何设置Python的运行环境。
如有任何问题,可以留言交流,因为P4D的资料实在太少,所以需要大家多交流。