- 最近用python写了一个小程序,想发布出去让人试用又不想暴露源码,搜索了一下发现将py文件编译成pyd文件就能达到目的。转换过程很简单,但是在调用pyd文件并且打包为单个exe文件的时候遇到一个坑,搞了一天才解决,在这里分享一下。
首先安装cython库,个人比较喜欢用清华的镜像库,速度快。
pip install Cyphton -i https://pypi.tuna.tsinghua.edu.cn/simple
from distutils.core import setup
from Cython.Build import cythonize
setup(ext_modules=cythonize("BetaV14.py"))
- BetaV14.py就是要转换为pyd文件的代码文件。 命令行输入:
python setup.py build_ext --inplace
- 会在.py文件目录下生成一个BetaV14.cp37-win_amd64.pyd文件,文件名中“.cp37-win_amd64”这一段可以删除,不删除也可以正常调用;但原文件名字段不能改变。
- 接下来需要打包发布为.exe文件,我用的是pyinstaller,还是用清华镜像库安装。
pip install pyinstaller -i https://pypi.tuna.tsinghua.edu.cn/simple
pyinstaller -F BetaV14.py
- 就能直接引用pyd文件打包发布exe文件,但是在我这里出现文件缺失的错误:
ValueError: Module file F:\python项目1\BetaV14.py is missing
- 继续查找问题,发现需要用一个入口程序来导入pyd文件,于是创建一个main.py文件,import刚才生成的模块,pyd文件默认优先级高于py文件,可以在后面解包exe文件来验证。
import BetaV14
if __name__ == '__main__':
BetaV14()
- 这里需要注意的是程序的__main__入口只能有一个,如果源py文件中有定义main入口,需要注释掉并调整代码缩进,否则通过main.py调用pyd文件遇到if name == ‘main’:之后的代码都不会运行。
- 接着命令行输入:
pyinstaller -F main.py
- 打包成.exe文件,在dist目录下发现main.exe文件大小只有5M,之前采用py文件打包的程序有接近50M,运行之后闪退。这个问题想了半天才想出来,可能是引用了大量的第三方库没有打包进去,于是将源py文件头部import部分全部复制到main.py文件头部。
import win32gui
import win32api
import win32con
import time
import random
import datetime
import os,sys
import configparser
import numpy as np
from PIL import Image
from scipy.signal import convolve2d
import http.client
import subprocess
import BetaV14
if __name__ == '__main__':
BetaV14()
- 再次用命令
pyinstaller -F main.py
打包,得到正常大小的.exe文件,点击能正常运行。
接下来我们用pyinstxtractor.py(不清楚该脚本是否涉及著作权,请自行搜索)解包exe文件验证一下,命令行输入:
python pyinstxtractor.py main.exe
- 会得到一个main.exe_extracted文件夹,在文件夹下发现文件BetaV14.pyd,说明通过引用pyd文件打包成功。
- 在此作为一个初学者记录一下自己遇到的坑,让大佬们见笑了。