| 我当前情况是,我第一次使用python,关于PYTHON的一切认识都为零。使用它是因为在网络通过一帖子介绍,使用三行就实现了视觉OCR识别。 经过测试效果杠杠的,所以想搞成DLL供WINDOWS下使用,因为我熟悉MFC。
 
 经过我几天的摸索,是可以实现将PYTHON代搞成DLL或EXE文件的,
 并且可以打包成在没有安装PYTHON环境下使用。
 开始前自己得准备安装好三个编程软件。
 0.VS2019.
 40多GB大小,微软自家的工具,随处可下载;
 
 1.pycharm.
 python编程,我安装的IDE(编程软件)是pycharm-community-2021.1.1
 这个软件到处都可以下载的到,就不贴网址了,小白都喜欢最新版本的,
 我也是,所以下载了最新版本的。
 
 2.Anaconda3.
 这是个好工具,好比手机上APP商城,python用到的工具,都可以统一用此软件下载安装。
 方便至极,比如后面要用到的pyinstaller,virtualenv 都可以直接在这工具上,通过界面操作,
 下载与安装。网络能 找到的都是通过指令执行,小白很难理解与操作。
 另外python有很多版本如版本2,版本3,各版本差别很大不兼容。
 这样的话Anaconda3可以很方便创建任意版本的python环境。
 官方下载网速不快,一会10KB,一会100kb的,可以在下边网址下载,网速满格。
 Anaconda3各版本下载:
 https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/
 
 三个软件我都选择最新版本的下载。
 三个软件都下载与安装好后,可以打开Anaconda3,
 新建一个python环境,如下图easyocr。
 
 python如何打包成动态库DLL与可执行程序EXE脱离环境运行   
 新建一个新的环境后,可以如上图,选择 ALL,再搜索想要安装的补助工具名称,
 点击更新,实现下载与安装。
 比如搜索pyinstaller或virtualenv,界面非常简洁很容易入手,自己多看看如何操作。
 后面会用到这两工具,如果没安装的话,在pycharm内使用指令会不识别。
 界面还是很简单的,第一次使用可多加操作。
 主要要理解的是在创建一个python项目工程时,有个python环境要设置。
 而Anaconda3就是可以创建任意python环境用。
 
 Anaconda3我安装的目录是D:\ProgramData\Anaconda3,
 这是默认的一个python环境。
 刚才创建的python环境easyocr及以后创建的环境会生成保存在文件夹envs内。
 如 D:\ProgramData\Anaconda3\envs。
 以上都准备好后,来看一个如何将编程好的python文件打包成DLL动态库文件供外部调用。
 
 一.python打包成动态库DLL并脱离环境调用。
 python调包功能极其强大,印象深刻,但编写的程序想要独立运行。
 也就是在其他没有安装PYTHON的电脑运行,操作起来特别麻烦,又是要这个工具,又是要那个文件的。
 下面来看一个我摸索成功的过程,供会员与后期自己参考。
 
 0.编写py文件实现程序功能。
 pycharm新建一工程,工程使用先前创建的pycharm环境。
 
 python如何打包成动态库DLL与可执行程序EXE脱离环境运行   创建测试py文件run.py。
 内容如下,实现两数值相加。
 
 python的py文件要生成dll动态库,是通过一个工具叫作cython来实现的,复制代码def str_add(str1, str2):
    return int(str1) + int(str2)
cython网上介绍说,python其一个子集,可编写支持python与C语言代码。
 也什么不能在pycharm上统一实现?第一次使用python,所以有点不理解。
 这里直接给出上边代码对应的cython代码。
 cython的语法我也不熟悉,下边的代码拿去套用也够用。
 复制代码cdef public str_add(str1,str2):
         return int(str1) + int(str2)
可以手动在上面文件run.py同级目录下创建一txt文件,手动复制内容,手动保存为run.pyx文件。
 第一次使用pycharm? run.py文件在哪呢?
 在pycharm界面,选中run.py文件,鼠标右键,可以看到open in菜单项,内有打开文件所以目录。
 准备好上边的两文件后,就可以执行命令代码了cython run.pyx。
 前提是cython工具事先要安装成功。
 前面我们使用Anaconda3创建了一个python环境exayocr,
 用pycharm创建的工程是基于此python环境。
 
 所以先关闭pycharm,打开Anaconda3,选择python环境exayocr,如上边第一图片,搜索cython下载安装。
 这里关闭pycharm,是因为其使用的环境有变化,要重启才生效。
 重要的事说3遍吧,很多情况都没意识到这点。
 pycharm重启生效。
 pycharm重启生效。
 pycharm重启生效。
 
 第一个次pycharm?那么命令窗口又在哪打开执行呢?
 pycharm窗口,最最最左下角,有个小下方形图标,点击可以看到一个terminal,选择就可以打开窗口执行命令。
 和cmd相似。
 run.py一般默认是在C盘,可以通过上面的方法打开其所在目录。
 我测试时将两文件run.pyx,run.py放在C:\Users\baikhgmv\Desktop\222。
 这样我在pycharm的命令窗口输入
 C: 回车,
 cd C:\Users\baikhgmv\Desktop\222 回车。
 这样以命令方式打开文件夹C:\Users\baikhgmv\Desktop\222
 
 命令窗口再输入cython run.pyx -3 回车。
 表示用python 3版本库生成run.h和run.c两文件,也就是VS2019可以打开的cpp,h类型文件。
 可以打开刚才的文件夹C:\Users\baikhgmv\Desktop\222查看。
 
 随后这个两个文件可通过调用python的C-API实现了run.py文件相同功能。
 如何编写呢?下面是模板代码,
 可自己新建一个CPP文件dllmain.c使用,放在run.h和run.c两文件一起。
 
 上面部分是PYTHON库内函数,部分是C语言上熟悉的代码,主要关注自定义的导出函数_str_add名。复制代码#include <Python.h>
#include <Windows.h>
#include "run.h"
 
extern __declspec(dllexport) int __stdcall _str_add(const char * a, const char * b) {
    return PyLong_AsLong(str_add(PyUnicode_FromString(a),PyUnicode_FromString(b)));<br>
}
 
BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpReserved) {
    switch( fdwReason ) {
        case DLL_PROCESS_ATTACH:
            Py_Initialize();
            PyInit_run();  #dll初始化的时候调用,这是python3的写法,python2改成,initrun()。参见生成的run.h
            break;
        case DLL_PROCESS_DETACH:
            Py_Finalize();
            break;
    }
    return TRUE;
}
 1.生成动态库DLL文件。
 那么这个新建的文件dllmain.c如何生成动态库DLL呢?
 网上介绍的一种方法是通过命令实现,也就是调用微软自家的程序cl.exe来实现。
 
 
 
 先来看这种方法的实现,后面还会介绍如何通过VS2019来直接编译。
 按上面一步步操作后,可在PYCHARM的命令操作继续输入
 cl /LD dllmain.c run.c -ID:\ProgramData\Anaconda3\envs\easyocr\include D:\ProgramData\Anaconda3\envs\easyocr\libs\python38.lib 回车。
 上边命令执行成功的前提是cl.exe路径必须在电脑系统的环境变量中,执行编译时用到的头文件/库路径,也得在环境变量中。
 一般电脑系统环境变量都没有配置,所以不会成功,所以得自己手动配置环境变量。
 繁琐的很哦。
 D:\ProgramData\Anaconda3\envs\easyocr\include D:\ProgramData\Anaconda3\envs\easyocr\libs\python38.lib 首先这两路径应该可以找到吧。
 前面用Anaconda3创建的python环境目录下有。
 dllmain.c run.c两文件是刚才命令窗口打开的目录下的两文件。
 
 那么如何给程序cl.exe配置系统环境变量呢?
 可以参考我操作使用的路径,都选择64位版本的。
 
 复制代码PATH追加cl.exe路径
D:\Program Files (x86)\vs2019\Enterprise\VC\Tools\MSVC\14.27.29110\bin\Hostx64\x64
LIB 新添加
C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\ucrt\x64
C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\um\x64
D:\Program Files (x86)\vs2019\Enterprise\VC\Tools\MSVC\14.27.29110\lib\x64
INCLUDE 新添加
C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\ucrt
C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\shared
C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\um
D:\Program Files (x86)\vs2019\Enterprise\VC\Tools\MSVC\14.27.29110\include
python如何打包成动态库DLL与可执行程序EXE脱离环境运行   
 电脑的系统环境变量如何设置如何添加就不介绍了,到处都是。
 可多次执行上边的编译命令,遇到什么lib库文件找不到,什么h头文件找不到。
 那就在库或头文件上一级/上上一级等等,查找文件名称,
 再将其所在路径配置到系统环境变量,重新执行就好。
 操作时一定要注意cl.exe及库文件都有32、64位之分,不要混合了。
 操作时一定要注意cl.exe及库文件都有32、64位之分,不要混合了。
 操作时一定要注意cl.exe及库文件都有32、64位之分,不要混合了。
 
 命令执行成功会在文件dllmain.c同级目录生成多个文件如dllmain.dll,dllmain.lib等。
 这就是我们想要的文件。
 
 上面是通过程序cl.exe,配合命令来编译生成动态库方法。
 非常繁琐,过两天什么是python我都不记得了,
 鬼记得这玩意是什么,命令又是什么?
 
 那么有没通过界面方式来生成动态库呢?
 所以我还尝试了使用VS2019来编译dllmain.c,run.c,run.h三个文件,生成动态库。
 打开VS2019,创建动态库工程,只为测试用所以一切保持默认,最终生成工程Dll1。
 工程文件夹内的dllmain.cpp对应dllmain.c,
 我直接复制dllmain.c内容覆盖dllmain.cpp的,再添加库python38.lib的引用,内容如下
 
 再将文件run.h,run.c导入到工程。复制代码#include <Python.h>
//#include <Windows.h>
#include "pch.h"
#include "run.h"
#pragma comment(lib,"python38.lib")
extern __declspec(dllexport) int __stdcall _str_add(const char* a, const char* b) {
    return PyLong_AsLong(str_add(PyUnicode_FromString(a), PyUnicode_FromString(b)));
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved) {
    switch (fdwReason) {
    case DLL_PROCESS_ATTACH:
      //  Py_SetPythonHome(L"D:\\ProgramData\\Anaconda3" );
        Py_Initialize();
        PyInit_run();
        break;
    case DLL_PROCESS_DETACH:
        Py_Finalize();
        break;
    }
    return TRUE;
}
其次是python头文件,库文件路径在工程的设置。
 看代码中你应该有注意到,有用到Python.h,python38.lib,所以还得设置其路径。
 如何设置就不用多说了,极为常见问题,到处都有教程。
 路径很多,Anaconda3所建立的每个python环境下的都可以用。
 我用的如下,
 D:\ProgramData\Anaconda3\envs\easyocr\include
 D:\ProgramData\Anaconda3\envs\easyocr\libs
 
 python如何打包成动态库DLL与可执行程序EXE脱离环境运行   
 都准备好后,编译发现还有预编译头文件相关问题。
 也就是pch.h这个文件再捣鬼,它的目的主要是提升编译速度。
 我就这点东西,不需要它提升,直接选择不用:项目属性--C/C++--预编译头--不使用预编译头。
 这一步步操作,我都是选择64位,编译也是64位release版本。
 python默认没安装debug版本,所以注意。
 一切顺利编译便可生成动态库文件dll.
 
 2.那么生成的动态库那如何使用呢?
 动态库的调用就很简单了,熟悉窗口编程的朋友,这都是小问题,
 有种回到自家地盘的感觉。
 在VS2019创建dos的空工程,刚才生成的动态库文件记得复制过来Dll1.lib,Dll1.dll。
 新建源文件,复制下面代码测试效果。
 
 例程一跑,你会发现,又是一堆错误。复制代码#include "stdio.h"
#include "stdlib.h"
extern __declspec(dllexport) int __stdcall _str_add(const char* a, const char* b);
#pragma comment(lib,"Dll1.lib")
int main()
{
        printf("%d \n", _str_add("123", "456"));
        getchar();
        return 0;
}
想想挺恶心的,一路走来多不容易,到最后还有一堆问题。
 
 python如何打包成动态库DLL与可执行程序EXE脱离环境运行   
 没办法,谁叫你要用它。
 其实图片是有提示的 PYTHONHOME = (not set),还有PYTHONPATH。
 也就是python的系统环境变量没有设置。
 dll是生成了,但它运行还是得依赖python库啊。
 平常我们用VS2019等编写的程序可在其他台电脑使用,那是因为微软默认每个系统都给你准备好了运行库。
 python是没有的,解决这问题有多种方法,第一如上边屏蔽的代码
 // Py_SetPythonHome(L"D:\\ProgramData\\Anaconda3" ); 设置python库所以位置(保证电脑内有安装了python)。
 第二种也是通过系统环境变量来指定路径。
 第三种就是打包程序用到的python库,放在一起使用。
 
 上边两程序生成的Dll1.dll,Project1.exe复制到D:\\ProgramData\\Anaconda3是可以直接运行的。
 这样我们就实现了py文件生成动态库dll,再调用这个库文件,正常执行程序。
 
 但要真正发布程序呢?
 这目录下的文件10个GB左右,一同发布是有点恐怖。
 所以最后还涉及一个打包问题,减少发布的程序尺寸。
 那么如何打包了呢?
 
 3.脱离PYTHON环境,打包发布程序。
 这里又要用到另外一个工具pyinstaller再配合工具virtualenv。
 经过测试全部文件共40MB左右,压缩一下再发布还是能接受的。
 这里看到这些工具一个接一个的来,真有点受不了。
 真有点跟菇凉谈恋爱,还得先认识她的七大姑八大姨。
 好在Anaconda3很方便,如下图,搜索工具名称,下载安装就好。
 工具安装了,接下来在python里使用的命令才可以识别。
 注意安装工具后记得重启python。
 
 
 先前我们编写的python文件run.py,已经转换成了dll。
 如果想打包成exe发布也是可以的,用到的工具都是上面提到的。
 不管是将run.py搞的DLL,或是EXE发布。
 run.py,DLL,或EXE二者所依赖的python库文件是都相同的,
 所以打包操作一样,打包生成的文件通用。
 
 打开python界面,打开其命令窗口。
 命令窗口默认是留在先前选择的目录C:\Users\baikhgmv\Desktop\222。
 没有话,按上面介绍的再打开这个目录,因为这目录我们先前放置有run.py文件。
 打包要用到。
 依次在命令窗口执行如下指令: # 及后面的内容为注释,不是指令;
 
 0.virtualenv envpack 回车  # 创建新的环境,python包依赖比较庞大,创建新环境可以减少最终引入的包。
 1.cd envpack 回车 #进入刚创建的文件夹,即C:\Users\baikhgmv\Desktop\222\envpack ;
 2. #手动将run.py复制进去。
 3.Scripts\activate # 激活并切换到virtualenv环境。
 4.pyinstaller run.py # 执行打包命令,或pyinstaller -F run.py;
 5.Scripts\deactivate # 打包成功后,使用命令取消激活环境;
 可以再次进入C:\Users\baikhgmv\Desktop\222\envpack。
 里面所生成的全部文件就为你程序所依赖的,自己整理使用。
 
 二.python生成exe,打包发布。
 方法如上所述,一样。
 帖子涉及的dll工程附件。
 
 
 
 
 |