在上一篇文章中的移植性一段中留了一个小尾巴,就是关于今天要聊的问题
如果 Pythone4Delphi 不能解决 Python 引入第三方库的问题,那么这个项目将变的毫无意义。
procedure TForm1.FormCreate(Sender: TObject);
begin
PythonEngine1.DllPath := ExtractFilePath(Application.ExeName) + 'python-3.10.6';
PythonEngine1.RegVersion := '3.10'; //<-- Use the same version as the python 3.x your main program uses
PythonEngine1.APIVersion := 1013;
PythonEngine1.DllName := 'python310.dll';
PythonEngine1.LoadDll;
PythonEngine1.SetPythonHome(ExtractFilePath(Application.ExeName) + 'python-3.10.6')
end;
代码相比于上一篇仅仅是多了一行 SetPythonHome 简单的说就是设置 Python 的家目录
其实有一种非常简单的办法就是把 Python 的安装目录复制一份,然后放到 Delphi 代码中指定的 Python 家目录中。但是这种方法也是最先被我放弃的 。
那么在放弃这种方法之后,我想到了另一种解决办法,不过需要分成两步
将本机当前的 Python 打包成一个无任何第三方依赖的基础环境。具体的实现方式有两种
利用 virtualenv 或者 miniconda(群里宝爷指点)
手动提取
提取第三方依赖,和 Delphi 程序一起发布。大概也有两种方式
freeze :此种方式会将环境中所有的包都打包进去
pipreqs:此类方法推荐使用,他只是总结程序中所用到的包,并不是电脑中安装的所有的包
我对 Python 不熟悉,所以暂时只能想到这种方法
经过测试,只需要复制特定的几个文件就可以完成 Python 的基础运行,我并没有研究他们的取别和联系
├─py
| ├─hello.py
└─python-3.10.6
├─python310.dll
├─python310.zip
├─DLLs
└─Lib
└─site-packages 第三方模块
|-Project1.exe
至于为什么需要这种目录结构,原因很简单,在我们指定了 SetPythonHome 之后它貌似只能读取这样的目录结构。我们也可以通过 Python 代码查看
import sys
print(sys.path)
这里我以爬虫使用频率最高的 requests 模块为例,其他模块的套路大同小异。示例代码如下(hello.py):
import requests
x = requests.get('https://www.baidu.com/')
x.encoding='utf-8'
print(x.text)
在该文件所在的目录打开控制台,执行以下命令
# 安装模块
pip install pipreqs
# 生成 requirements.txt,该文件记录了我们当前的 Python 项目中所引用的模块
pipreqs ./ --encoding=utf8
这样并未完成,它仅仅是生成了 requirements.txt。我们还需要将依赖抽取下载到指定的目录
#它的目的是为了生成 .whl 文件
pip download -d ./download -r requirements.txt
# 将 .whl 生成 py 文件到指定目录
pip install --no-index --find-links=./download --target=./package -r requirements.txt
最后一步,将 package 文件夹中的内容复制到 SetPythonHome\Lib\site-packages 目录下即可
我这里用的是相对路径,建议还是用绝对路径吧,此外也可以将 --target 的值指定为 site-packages 这样就不用复制了
至此打包第三方模块完成,或许还有更好的办法,只是我不知道而已。最后放一张执行的结果图
最后的最后还是推一下新号,有兴趣的朋友可以关注一波