Python-python打包编译成pyd或者.so,保护代码。

2020-05-20

一、准备工作, setup.py的打包
Standard commands:
build build everything needed to install
build_py "build" pure Python modules (copy to build directory)
build_ext build C/C++ extensions (compile/link to build directory)
build_clib build C/C++ libraries used by Python extensions
build_scripts "build" scripts (copy and fixup #! line)
clean clean up temporary files from 'build' command
install install everything from build directory
install_lib install all Python modules (extensions and pure Python)
install_headers install C/C++ header files
install_scripts install scripts (Python or otherwise)
install_data install data files
sdist create a source distribution (tarball, zip file, etc.)
register register the distribution with the Python package index
bdist create a built (binary) distribution
bdist_dumb create a "dumb" built distribution
bdist_rpm create an RPM distribution
bdist_wininst create an executable installer for MS Windows
upload upload binary package to PyPI
check perform some checks on the package

Extra commands:
rotate delete older distributions, keeping N newest files
develop install package in 'development mode'
setopt set an option in setup.cfg or another config file
saveopts save supplied options to setup.cfg or other config file
egg_info create a distribution's .egg-info directory
install_egg_info Install an .egg-info directory for the package
alias define a shortcut to invoke one or more commands
easy_install Find/get/install Python packages
bdist_egg create an "egg" distribution
test run unit tests after in-place build
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
其中几种尝试的方式,均尝试了一下,以下将逐个讲述,实验过程。

二、py\pyc\pyo\pyd的区别
py: python 脚本文件(source code)
pyc: 脚本文件编译得到的字节码, 二进制文件,python文件经过编译器编译之后的文件。可以提高文件加载速度
pyo: 脚本文件开启优化编译选项(-O)编译得到的字节码,二进制文件,优化编译后的文件。可以通过python -O file.py生成。
pyd: 基本的Windows DLL文件, python的动态链接库。
三、生成pyd二进制文件(方法一)。
不同的系统生成的文件不同,根据自己实际情况选择合适的工具和系统。

windows环境下生成的是pyd文件
linux环境下生成.so文件
背景:考虑到实际人员可能没有使用Pycharm工具进行开发,因此以下主要步骤直接通过命令行进行执行,以下的实验是一个打包的小demo,实际针对大工程还需要解决打包需要的依赖、包含一些媒体文件等等,具体情况具体分析。除此之外,进行这种方式的打包与python版本无关,使用的是python中Cpython第三方模块,所以,不需要考虑python的问题。

主要步骤如下:

第一步:在新建的test文件夹下建立需要打包的文件,本实验中采用util1.py,打包的文件可以根据自己习惯命名,在打包文件setup.py文件中对应修改文件名称即可。

test文件夹下目录:


构建其中util1.py文件,代码如下

class util_1:
def fun_Hello(self, s):
return s
1
2
3
第二步:构建setup,py文件,并使用setup.py进行打包

setup.py文件内容如下:

from setuptools import setup
from Cython.Build import cythonize

setup(
name='test',
ext_modules=cythonize('util1.py'), # 打包文件的名称,默认与setup.py在同一路径下
)
1
2
3
4
5
6
7
第三步:在setup.py文件所在目录下打开终端,并进行如下命令

python setup.py build_ext --inplace
1
命令行运行结果:


第四步:检查运行结果。运行上述过程后,在test文件夹下会生成对应的c文件、so文件和编译过程中间文件build文件夹。

第五步:得到的 util1.cp36-win_amd64.pyd 的可以直接当成模块,可以通过python直接调用,在test文件夹下,新建test.py文件,其中代码如下:

from util1 import util_1

if __name__ == '__main__':
obj1 = util_1()
print(obj1.fun_Hello("sssssssss"))
1
2
3
4
5
运行的结果如下:


问题分析
可能出现的问题:

1. ‘ImportError: No module named xxx’
原因:可能是xxx.pyd所在路径不在sys.path中。

解决方法:import之前用sys.path.append()方法加入xxx.pyd所在路径,确定当前路径推荐用os.path.realpath('.')。

2. ‘ImportError: DLL load failed: 找不到指定的程序’
原因:可能是xxx.pyd调用了其他的DLL文件,且其调用的DLL文件无法被搜索到。

解决方法:用dependency walker查看xxx.pyd依赖的DLL,然后有两种方案

(1)将所有DLL放入xxx.pyd所在目录

(2)单独建立存放DLL文件的目录,比如D:\test\DLLFiles。用os.environ['path']方法加入到环境变量PATH中

这里import很容易遇到路径报错的问题。如图:

这个错误查了下,解决方法:import之前用sys.path.append()方法加入xxx.pyd所在路径,确定当前路径推荐用os.path.realpath(’.’)。
因为使用Python import 模块时,

先会在模块的搜索path里依次搜索(前面会覆盖之后出现的同名模块),次序为:

程序的主目录(交互模式下当前的工作目录或 脚本文件所在的目录)。
环境变量 PYTHONPATH目录(如果已经进行了设置)。
标准链接库目录(标准库模块所在目录 C:\Python27或C:\Python27\Lib\site-packages 目录中)。
任何放在标准链接库目录中的.pth文件中记录的目录。
我这里是用的第一个方法:

import sys
sys.path.append("D:\\pycharmproject\\test") # 修改为当前自己的工程目录路径
from util1 import util_1

print(util_1().fun_Hello("ssssssss"))
1
2
3
4
5
四、 生成pyd二进制文件(方法二)
与方法一的情况类似,在方法一的基础上很容易进行方法二,实验步骤如下。

第一步、安装cython

pip install cython
1
由于我的环境中已经安装cython,命令行中出现的是。

如果安装没提示错误信息说明,上一步环境正确,并且cython安装正确。

第二步:安装easycython

试了一些方法和库,这个最方便只要一行代码就可以搞定。
https://github.com/cjrh/easycython

pip install easycython
1
这个模块也会自动安装依赖的cython,如果上步安装cython失败,也可以直接尝试安装easycython来试。

第三步:转换步骤

将.py文件重命名为.pyx 运行以下命令

easycython *.pyx
1
上面会将当前文件夹下所有的.pyx文件生成为.pyd
如果只生成单个的main.pyx
main.pyx内容:

def test(): print('Hello sanfenzui!')
1
开始生成:

easycython main.pyx
1
第四步:修改名称

生成文件main.cp35-win_amd64.pyd
手动将其重命名为main.pyd
注意:这里重命名时去掉“.cp35-win_amd64”不要更改前面的名字,否则不能正常引用
然后python环境下
import main #保证当前文件夹下没有main.py或者main.pyc

main.test()
1
实验三、生成本地压缩包,安装部署源码到环境中
https://blog.csdn.net/qq_39852676/article/details/99745224
————————————————
版权声明:本文为CSDN博主「燕山-赵凯月」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_39852676/article/details/99842637

猜你喜欢

转载自www.cnblogs.com/zhangchao0515/p/12924615.html
今日推荐