目录
前言
最近一直在研究针对python文件加密的技术,之前介绍的混合编程方法虽然也能做到加密的效果,但是需要同时写python与C/C++,对于不会C/C++的同学而言,就显得稍微麻烦了点。今天介绍一下通过Cython中的Cythonize编译python文件,生成so库文件给python进行调用的方法。
Cythonize使用
python文件准备
首先,需要准备一个python文件,其中可以编写类或者函数
def fib(n):
"""Print the Fibonacci series up to n."""
a, b = 0, 1
while b < n:
print b,
a, b = b, a + b
发布脚本准备
然后为了生成一个Cython的扩展模块,还需要一个发布脚本
from distutils.core import setup
from Cython.Build import cythonize
setup(
ext_modules=cythonize("fib.py"),
)
so文件编译
最后我们可以执行下列命令,就可以在linux环境下生成对应的so文件
python setup.py build_ext --inplace
模块使用范例
完成了上述步骤后,我们就可以简单地使用这个模块了
>>> import fib
>>> fib.fib(2000)
可以看出该模块下有fib的属性方法,但是当我用ctypes模块调用的时候,却出现了错误
import ctypes
import os
# 切换到so文件所在目录
parent_path = os.getcwd()
for second_path in os.listdir(parent_path):
file_path = os.path.join(parent_path, second_path)
if "so" in file_path:
mod = ctypes.cdll.LoadLibrary(file_path)
print(dir(mod))
print(mod.fib(2000))
报错信息如下:未申明fib函数
为了验证so文件能够被直接使用,将so文件直接拷贝到另外一台环境相近的机器上,可以直接使用。但是值得注意的是,这种方式编译生成的so文件只能在相同环境中使用,否则会报错。
比如我们不能够在python3.5的环境中使用python2.7打包的模块,二者有很大的区别。
在python2.7中,可以使用的so文件格式如下:
[('.so', 'rb', 3), ('module.so', 'rb', 3), ('.py', 'U', 1), ('.pyc', 'rb', 2)]
在python3.5中,可以使用的so文件格式如下:
[('.cpython-35m-x86_64-linux-gnu.so', 'rb', 3), ('.abi3.so', 'rb', 3), ('.so', 'rb', 3), ('.py', 'r', 1), ('.pyc', 'rb', 2)]
扩展
如何在Spark集群上调用Cython编译的so文件
当我们的使用场景是集群,我也采取了以下几种方式来尝试:
- 方式一:使用--files传输文件,再使用sys.path.append()添加路径
- 方式二:使用--files传输文件,使用imp或者importlib读取文件
- 方式三:直接将so文件打包成zip压缩包,对外提供一个接口,再通过--py-files选项上传到集群
经过尝试后发现其中方式一、二都可以正常运行,但是方式三会提示错误信息,为此我们得出以下结论:
- 不能在外面直接引用data.zip里面的so文件
- data.zip包里面的文件也不能引用包中的so文件
- 外部的so文件能够引用zip压缩包中的python文件
因此,综合来看,so文件必须在外部放置才能够引用。
总结
今天主要介绍了借助cyhton中的Cythonize将python语言转化成C/C++语言,再编译成so文件,从而实现算法代码加密的目的。从中可以看出该方法简单方便,只需要有python语言基础即可,但是缺点也很明显,兼容性很差,编译好的so文件只能在相同环境中使用。