使用cython的代码保护方案

简介: 建模开发平台即将推出了镜像构建的功能,以方便用户将开发好的代码迁移至其他环境执行。但在迁移过程中难免会有代码保护的需求,现提供一种基于cython的代码保护方案,能够在一定程度上解决代码保护的问题。

参考文档:

https://cython.org/

https://github.com/cython/cython

https://zhuanlan.zhihu.com/p/54296517


Cython介绍

Cython是一个类似于Python的编程语言,它是基于Python语言的扩展和优化。Cython语言是一种静态类型语言,同时也支持Python的动态类型特性,Cython代码会被转换成C语言代码,再编译成机器码,因此其执行速度比Python要快。

虽然Cython 的主要目的是带来性能的提升,但是基于它的原理:将 .py/.pyx 编译为 .c 文件,再将 .c 文件编译为 .so(Unix) 或 .pyd(Windows),其带来的另一个好处就是难以破解。但需要注意的是,cython本质上并非提供加密功能,而是通过编译成二进制文件后,提高他人阅读核心代码的难度,使用此方法加密代码还要注意代码安全。


方法

1)编写 setup.py:

可根据cython官方文档的指引,对您的代码进行编译。以下代码可供参考:

此脚本将会找到当前目录下所有含__init__.py文件的目录,并对他们进行编译,并在原地生成.so文件。

#encoding=utf-8fromsetuptoolsimportsetup, find_packagesfromsetuptools.extensionimportExtensionfromCython.BuildimportcythonizefromCython.Distutilsimportbuild_extfrompathlibimportPathimportshutilimportsys, os# some global variable, don't change them if you don't know what they meanmy_build_dir="build"classMyBuildExt(build_ext):
defrun(self):
build_ext.run(self)
build_dir=Path(self.build_lib)
root_dir=Path(__file__).parenttarget_dir=build_dirifnotself.inplaceelseroot_dirformoduleinmy_packages:
module=module.replace(".","/")
module_path=Path(module)
print(">>find modeule path:"+str(module_path))
self.copy_file(module_path/'__init__.py', root_dir, target_dir)
self.copy_file(module_path/'__main__.py', root_dir, target_dir)
forpinPath('.').iterdir():
ifp.is_file() andp.suffixnotin [".py", ".pyc"] andp.namenotinexclude_list:
self.copy_file(p, root_dir, target_dir)
print("copy end")
defcopy_file(self, path, source_dir, destination_dir):
ifnot (source_dir/path).exists():
returnshutil.copyfile(str(source_dir/path), str(destination_dir/path))
deffind_scrips():
scrips_list= []
forpinPath('.').iterdir():
ifp.is_file() and (p.namenotinexclude_list):
ifp.suffixin [".py"] and (notp.name.startswith(".")):
scrips_list.append(p.name)
print("find scrips:")
print(scrips_list)
print(exclude_list)
returnscrips_listif__name__=="__main__":
my_project_name="test"my_clang="gcc "ifos.path.isdir(my_build_dir):
print("Exist build dir, auto remove")
shutil.rmtree(my_build_dir)
print("===============start=================")
exclude_list= ["setup.py", ".DS_Store"]
os.environ["CC"]=my_clangmy_packages=find_packages()
print("packages:")
print(my_packages)
ext=[]
#找到所有的packageformoduleinmy_packages:
module=module.replace(".","/")
ext.append(Extension(module+".*", [module+"/*.py"]))
#找到根目录下的脚本ext.extend(find_scrips())
print("Extension:")
print(ext)
setup(
name=my_project_name,
ext_modules=cythonize(
ext,
build_dir=my_build_dir,
compiler_directives=dict(
always_allow_keywords=True            )),
cmdclass=dict(
build_ext=MyBuildExt        ),
packages=find_packages(where=".")
    )
print("===============end=================")

2)编译为 .c,再进一步编译为 .so 或 .pyd:

python setup.py build_ext --inplace

3)删除python源码,通过.so的方式进行执行:

find . -name'*py[c~]'-delete

4)编写启动脚本,执行过程中调用启动脚本:

from real_main import main
import sys
if __name__ =='__main__':
    main(sys.argv[1:])


注意事项

Cython 源代码的语法是 Python语法的一个超集,也就是说,任何可以在 Python 中使用的语法,也可以在 Cython 中使用。但是,以下几种 Python语法在 Cython 中是不支持的:

1.动态类型变量声明:在 Cython 中,变量必须是静态类型,需要在声明时指定数据类型。

2.不支持 eval() 函数和 exec语句:因为 Cython 是一种编译型语言,无法像 Python一样动态生成代码。

3.不支持生成器表达式和列表推导式:Cython 中不能直接使用生成器表达式和列表推导式,但是可以使用类似于 Python 中的 for 循环语句来达到相同的效果。

4.不支持一些 Python 内置函数:例如 zip(), filter(), map() 等,但是 Cython 提供了自己的实现,用于替代这些函数。

5.不支持 slots 特殊变量:Cython 中不支持 slots 特殊变量来限制类的属性,但是可以使用 cdef class 来实现类的属性限制。

6.不支持一些 Python 模块和库:例如 asyncio, logging 等,因为这些模块和库在 Cython 中不可用。

7.不支持 Python 的全局解释器锁(GIL):Cython 中没有 GIL,因此可以使用 Python 的多线程模块来实现并发编程。

相关文章
|
编译器 开发工具 C#
使用MindOpt时常见的报错,以及对应的解决方法
使用MindOpt时常见的报错,以及对应的解决方法
|
人工智能 自然语言处理 达摩院
MindOpt 云上建模求解平台:多求解器协同优化
数学规划是一种数学优化方法,主要是寻找变量的取值在特定的约束情况下,使我们的决策目标得到一个最大或者最小值的决策。
|
C语言 Perl 存储
优化求解器之MPS文件的格式简介
在使用MindOpt优化求解器解决实际问题时,其中重要的一环在于如何建立优化模型,以及存储优化模型以便于作为求解器的输入文件。存储优化模型的文件,其关键在于定义一种清晰的格式,用来说明优化模型的数学结构和相关的数据。接下来我们将发布一系列文章,对常见的MPS/LP等格式的模型文件和命名规范进行简要的介绍。
优化求解器之MPS文件的格式简介
|
达摩院 算法 Java
选择优化求解器的关键因素:以MindOpt为例
选择一款适合自己业务需求的求解器我们一般需要考量什么呢?可求解的问题类型?问题规模?本文将介绍一些需要考虑的重要因素,并且介绍阿里达摩院MindOpt优化求解器在这些因素下的表现。
|
人工智能 达摩院 开发工具
MindOpt不联网License,可直接在阿里云线上购买了
在很多场景里,由于智能决策运行环境不允许联网、网络不稳定、或者需要毫秒级计算决策方案需要节省联网耗时等场景,多用户反馈需要【不联网】的License。
MindOpt不联网License,可直接在阿里云线上购买了
|
达摩院 安全 调度
网络流问题--交通调度【数学规划的应用(含代码)】阿里达摩院MindOpt
本文探讨了如何利用数学规划工具MindOpt解决交通调度问题。交通调度涉及网络流分析,考虑道路容量、车辆限制、路径选择等因素,以实现高效运行。通过建立数学模型,利用MindOpt云平台和建模语言MAPL,设定流量最大化目标并确保流量守恒,解决实际的调度问题。案例展示了如何分配车辆从起点到终点,同时满足道路容量约束。MindOpt Studio提供在线开发环境,支持模型构建和求解,帮助优化大规模交通调度。
|
存储 并行计算 编译器
向量化代码实践与思考:如何借助向量化技术给代码提速
在不堆机器的情况下,要想使代码完全发挥出硬件性能,就需要做加速。其中比较常见的操作是并发处理,本文将深入向量化计算技术,为大家讲解SIMD指令,以及如何写出规范的可向量化的代码。
|
达摩院 供应链 JavaScript
网络流问题--仓储物流调度【数学规划的应用(含代码)】阿里达摩院MindOpt
本文通过使用MindOpt工具优化仓储物流调度问题,旨在提高物流效率并降低成本。首先,通过考虑供需匹配、运输时间与距离、车辆容量、仓库储存能力等因素构建案例场景。接着,利用数学规划方法,包括线性规划和网络流问题,来建立模型。在网络流问题中,通过定义节点(资源)和边(资源间的关系),确保流量守恒和容量限制条件下找到最优解。文中还详细介绍了MindOpt Studio云建模平台和MindOpt APL建模语言的应用,并通过实例展示了如何声明集合、参数、变量、目标函数及约束条件,并最终解析了求解结果。通过这些步骤,实现了在满足各仓库需求的同时最小化运输成本的目标。
|
存储 达摩院
「达摩院MindOpt」线性规划用于排程排程问题(03)
比上一篇问题02中,我们只考虑了一次性的采购和生产计划,实际中的排产排程问题要更加复杂和精细。例如,我们要考虑未来三个月内采购和排产排程计划。其中,原材料每个月的采买价格均有不同,并且原材料购买后的存储也需要成本开销。在本节中,我们将考虑这样一个相对复杂的排产排程的决策问题。
「达摩院MindOpt」线性规划用于排程排程问题(03)
|
达摩院 供应链 安全
光储荷经济性调度问题【数学规划的应用(含代码)】阿里达摩院MindOpt
本文介绍使用MindOpt工具优化光储荷经济性调度的数学规划问题。光储荷经济性调度技术旨在最大化能源利用率和经济效益,应用场景包括分布式光伏微网、家庭能源管理系统、商业及工业用电、电力市场参与者等。文章详细阐述了如何通过数学规划方法解决虚拟电厂中的不确定性与多目标优化难题,并借助MindOpt云建模平台、MindOpt APL建模语言及MindOpt优化求解器实现问题建模与求解。最终案例展示了如何通过合理充放电策略减少37%的电费支出,实现经济与环保双重效益。读者可通过提供的链接获取完整源代码。