【Pyhton4Delpi】学习笔记(二)安装验证篇

D12环境下安装P4D。

一、下载 Python4Delphi(下称P4D):

下载地址:https://github.com/pyscripter/python4delphi

下载或者克隆P4D到指定的目录,例如:MDS_New,目录结构如下,P4D就是克隆下来的控件全部目录。

 

二、安装P4D

        首先关闭正在运行的Delphi IDE!                

2.1 自动安装:

        在下载的目录InstallMDS_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"
2.1.1 选择需要安装的包,默认可以全部安装

2.1.2 选择需要安装的文件夹:

注意:

        勾选 Compile packages and install on IDE 选项,这样就会安装完成后,在控件面板上显示已经安装好的P4D控件。

        另外注意,这里选择目录是上一级目录,实际默认安装在这一级目录下的P4D目录中。

2.1.3 安装完成,点击:Finish 即可

2.2 手动安装

自动安装和手动安装是完全独立的安装方式,但只需要成功执行一次就可以。对于手动安装,比如已经将P4D克隆到了 D:\MDS_New\P4D 目录中。

2.2.1 打开Delphi IDE
2.2.2 设置搜索路径,增加如下地址
  • D:\MDS_New\P4D\Source
  • D:\MDS_New\P4D\Source\vcl
  • D:\MDS_New\P4D\Source\fmx

2.2.3 打开 D:\MDS_New\P4D\Packages\Delphi\P4DComponentSuite.groupproj 工程组

对于10.4+以上版本就选择10.4+,否则选择10.3-。 选择 Build All

2.2.4 选择  dclPythondclPythonVcl 和 dclPythonFmx 运行时包进行安装

三、查看安装是否成功

        打开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代码,就可以尝试运行了,举例:

1. Delphi 程序源代码
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.
2. Python 源代码
#-------------------------------------------------------------------------------
# Name:        module1
# Purpose:     判断素数测试
#
# Author:      wuxihong
#
# Created:     01-02-2024
# Copyright:   (c) wuxihong 2024
# Licence:     <your 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()

3. 说明

这是一个计算素数个数的演示程序,可以完全通过Python来计算,也可以在Python中调用Delphi的函数来计算,演示了如何设置Python的运行环境。

五、源代码及运行环境(38)下载

1. Delphi 源代码(内涵Python代码)
2. Python38运行环境 

如有任何问题,可以留言交流,因为P4D的资料实在太少,所以需要大家多交流。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/386383.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

localStorage、sessionStorage、cookie区别

localStorage: localStorage 的生命周期是永久的&#xff0c;关闭页面或浏览器之后 localStorage 中的数据也不会消失。localStorage 除非主动删除数据&#xff0c;否则数据永远不会消失 sessionStorage: sessionStorage 的生命周期是仅在当前会话下有效。sessionStorage 引入…

【小沐学GIS】基于C++QT绘制三维数字地球Earth(OpenGL)

&#x1f37a;三维数字地球系列相关文章如下&#x1f37a;&#xff1a;1【小沐学GIS】基于C绘制三维数字地球Earth&#xff08;456:OpenGL、glfw、glut&#xff09;第一期2【小沐学GIS】基于C绘制三维数字地球Earth&#xff08;456:OpenGL、glfw、glut&#xff09;第二期3【小沐…

基于Spring Boot的足球青训俱乐部管理后台系统,计算机毕业设计(带源码+论文)

源码获取地址&#xff1a; 码呢-一个专注于技术分享的博客平台一个专注于技术分享的博客平台,大家以共同学习,乐于分享,拥抱开源的价值观进行学习交流http://www.xmbiao.cn/resource-details/1757420859554869250

流量嗅探详解

不少人存在这样的观点&#xff1a;只要计算机安装各种专业的安全软件&#xff0c;系统及时更 新补丁&#xff0c;密码尽可能复杂&#xff0c;那么计算机就会避免遭到入侵。当然这样的确不容易 被入侵&#xff0c;但那也只是针对传统的病毒、木马而言&#xff0c;在流量攻击面前…

2.13作业

21.c 22.b 23.b 假设&#xff0c;入&#xff1a;12345&#xff0c;出&#xff1a;54132.要出5&#xff0c;必须12345按顺序入&#xff0c;然后出5&#xff0c;依次出4321&#xff0c;想要在4之后出1是不可能实现的。 24.b10,c11,d100 25.3 ,2 …

leetcode:45.跳跃游戏二

1.解题思路&#xff1a; 用最少的步数增加覆盖范围&#xff0c;直至覆盖到终点。 2. 代码实现&#xff1a; 如果数组长度为1&#xff0c;返回0 初始化cur&#xff0c;next&#xff0c;result为0 for循环遍历数组&#xff0c;使得next指向下一步能够覆盖的最远距离&#x…

人力资源智能化管理项目(day07:员工详情)

学习源码可以看我的个人前端学习笔记 (github.com):qdxzw/humanResourceIntelligentManagementProject 页面结构和路由 <template><div class"dashboard-container"><div class"app-container"><div class"edit-form">…

数学实验第三版(主编:李继成 赵小艳)课后练习答案(九)(3)

实验九&#xff1a;线性函数极值求解 练习三 1.设有三种证券 期望收益率分别为10%,15%和40%,风险分别是10%,5%和20%,假定投资总风险用最大一种投资股票的风险来度量,且同期银行存款利率为 5%,无风险,为投资者建议一种投资策略(投资比例),使其尽可能获得最大收益. clc;clear;…

【数据结构】链表OJ面试题4《返回链表入环的第一个结点》(题库+解析)

1.前言 前五题在这http://t.csdnimg.cn/UeggB 后三题在这http://t.csdnimg.cn/gbohQ 给定一个链表&#xff0c;判断链表中是否有环。http://t.csdnimg.cn/Rcdyc 记录每天的刷题&#xff0c;继续坚持&#xff01; 2.OJ题目训练 10. 给定一个链表&#xff0c;返回链表开始…

【Tauri】(3):使用Tauri1.5版本,进行桌面应用开发,在windows上搭建环境,安装node,rust环境,可以打包成功,使用vite创建应用

1&#xff0c;视频地址&#xff1a; https://www.bilibili.com/video/BV1Ny421a7nA/ 【Tauri】&#xff08;3&#xff09;&#xff1a;使用Tauri1.5版本&#xff0c;进行桌面应用开发&#xff0c;在windows上搭建环境&#xff0c;安装node&#xff0c;rust环境&#xff0c;可以…

9.【CPP】List (迭代器的模拟实现||list迭代器失效||list的模拟实现)

介绍 list是可以在常数范围内在任意位置进行插入和删除的序列式容器&#xff0c;并且该容器可以前后双向迭代。list的底层是双向链表结构&#xff0c;双向链表中每个元素存储在互不相关的独立节点中&#xff0c;在节点中通过指针指向其前一个元素和后一个元素。list与forward_…

文件压缩炸弹,想到有点后怕

今天了解到一个概念&#xff0c;压缩炸弹。 参考&#xff1a; https://juejin.cn/post/7289667869557178404 https://www.zhihu.com/zvideo/1329374649210302464 什么是压缩炸弹 压缩炸弹&#xff08;也称为压缩文件炸弹、炸弹文件&#xff09;是一种特殊的文件&#xff0c;它…

年假作业10

一、选择题 BBDBACCCAD 二、填空题 1,4,13,40 3715 358 5 2 6 1 5 4 8 2 0 2 三、编程题 1、 #include <iostream> #include<array> #include <limits> using namespace std; int main() {array<int,10> score;array<int,10>::iterat…

黑马程序员——移动Web——day01

目录&#xff1a; 平面转换 简介平移定位居中案例-双开门旋转转换原点案例-时钟多重转换缩放案例-播放特效倾斜渐变 线性渐变案例-产品展示径向渐变综合案例 导航-频道渐变按钮轮播图猜你喜欢 1.平面转换 简介 作用&#xff1a;为元素添加动态效果&#xff0c;一般与过渡配…

鸿蒙开发系列教程(十七)--路由Router

页面路由指在应用程序中实现不同页面之间的跳转和数据传递 1、页面跳转 跳转模式 router.pushUrl()&#xff1a;目标页不会替换当前页&#xff0c;而是压入页面栈。这样可以保留当前页的状态&#xff0c;并且可以通过返回键或者调用[router.back()]方法返回到当前页。router…

MATLAB|【免费】高比例可再生能源电力系统的调峰成本量化与分摊模型

目录 主要内容 部分代码 结果一览 下载链接 主要内容 程序复现文献《高比例可再生能源电力系统的调峰成本量化与分摊模型》&#xff0c;从净负荷波动的角度出发&#xff0c;建立了调峰成本的量化与分摊模型&#xff0c;构造了无调峰需求的替代场景&#xff0c;将…

Vulnhub靶机:DC4

一、介绍 运行环境&#xff1a;Virtualbox 攻击机&#xff1a;kali&#xff08;10.0.2.15&#xff09; 靶机&#xff1a;DC4&#xff08;10.0.2.57&#xff09; 目标&#xff1a;获取靶机root权限和flag 靶机下载地址&#xff1a;https://www.vulnhub.com/entry/dc-4,313/…

勒索DASH币CrySiS最新变种的同源分析

前言 CrySiS勒索病毒&#xff0c;又称为Dharma勒索病毒&#xff0c;首次出现于2016年&#xff0c;2017年5月此勒索病毒万能密钥被公布之后&#xff0c;导致此勒索病毒曾消失过一段时间&#xff0c;不过随后该勒索病毒就开发了它的最新的一款变种样本&#xff0c;并于2018年开始…

Linux中signal/kill/raise/abort函数(信号函数)

signal函数&#xff1a; 函数作用&#xff1a;注册信号捕捉函数 函数原型&#xff1a; typedef void (*sighandler_t)(int); sighandler_t signal(int signum, sighandler_t handler); 函数参数&#xff1a; signum:信号编号handler:信号处理函数 测试&#xff1a;给没有读…

669. 修剪二叉搜索树

给你二叉搜索树的根节点 root &#xff0c;同时给定最小边界low 和最大边界 high。通过修剪二叉搜索树&#xff0c;使得所有节点的值在[low, high]中。修剪树 不应该 改变保留在树中的元素的相对结构 (即&#xff0c;如果没有被移除&#xff0c;原有的父代子代关系都应当保留)。…