使用Cython编译Python源码加密加速,有这一篇就够了!

news2024/11/28 22:37:54

0 前言

python是一门脚本语言,运行时由python虚拟机解释执行。当我们使用python设计好算法给第三方使用时只能提供源码,任何运行我们算法的人都可以看到源码以及对应的算法思路。因此,需要一定手动保护源码。

最简单的保护方式是使用代码混淆,加大阅读难度。但这只是加大阅读难度,对方只要花点时间,还是可以理解算法思路。今天介绍使用Cythonpython源码编译成库文件(Windows平台为pyd文件,Linux平台为so文件),用户拿到库文件后,无法反编译为python源码,从而保证了代码安全性。另外,还能达到代码运行加速效果。关于Cython更详细内容这里不过多介绍,本文主要介绍如何使用Cythonpython编译为库文件使用。

最近看到一个巨牛的人工智能教程,分享一下给大家。教程不仅是零基础,通俗易懂,而且非常风趣幽默,像看小说一样!觉得太牛了,所以分享给大家。平时碎片时间可以当小说看,【点这里可以去膜拜一下大神的“小说”】。

1 场景实战

mobilenet v3识别ImageNet为例,项目目录如下所示:
初始算法项目结构
核心代码在src根目录下,各个代码文件作用:

  • src/model/mobilenetv3.py:定义模型网络结构
  • src/service/model_service.py: 定义模型创建、推理
  • test_img/test.jpg: 定义测试图片,图片内容为一架飞机
  • weights/mobilenetv3_small_67.4.pth.tar: 训练好的模型参数
  • test.py: 测试代码

看看test.py具体代码,其他文件无需过于关注,感兴趣的读者可以翻阅到本文末端获取完整代码。test.py具体代码如下:

from src.service.model_service import load_model, infer

model = load_model("weights/mobilenetv3_small_67.4.pth.tar")

class_idx, score = infer(model, "test_img/test.jpg")
print(class_idx, score)

运行上面代码,输出结果如下:

404 0.8282396

Imagenet中,索引为404的类别为客机,可以看到整体运行没有问题。

2 算法源码加密

好了,有了上面的算法场景后,接下来我们对以上场景中的算法源码加密。

2.1 环境准备

安装Cython

执行如下命令安装Cython

pip install Cython

安装c/c++编译环境

对于Linux读者,只要有gcc编译环境即可,这里不过多介绍。

对于windows读者,安装好最新的VisualStudio即可。没有安装VisualStudio的读者,可以前往https://visualstudio.microsoft.com/zh-hans/visual-cpp-build-tools/下载。

本文是在Winodws平台,使用VisualStudio 2022编译环境运行。

2.2 编写编译代码

注意,实际的编译代码由Cython实现,我们只是简单使用。主要是设置本地需要编译成pyd(或so)的python文件,无其他复杂内容, 读者可以直接拿去使用,注意修改代码根路径即可。创建文件compile.py内容如下:

import os
from setuptools import setup
from distutils.extension import Extension
from distutils.command.clean import clean
from Cython.Distutils import build_ext
 
def load_all(root):
    out = []
    if os.path.isdir(root):
        out.append((root, True))
        names = os.listdir(root)
        for name in names:
            p = os.path.join(root, name)
            if os.path.isdir(p):
                out += load_all(p)
            else:
                out.append((p, False))
    else:
        out.append((root, False))
    return out
 
def load_files(root, exts=("py",)):
    out = []
    for (p, is_dir) in load_all(root):
        if not is_dir:
            ext = p.split(".")
            if len(ext) > 1 and ext[-1] in exts:
                out.append(p)
    return out
 
def get_packages(root):
    out = []
    for (p, is_dir) in load_all(root):
        if is_dir:
            out.append(p)
    return out
 

# ex_files参数可以支持不在src文件夹下的文件进行加密
def get_extensions(root):
    py_files = load_files(root, exts=("py",))
    ext_names = map(lambda x: x.replace(os.path.sep, '.')[:-3], py_files) 
    def make_extension(ext_name):
        ext_path = ext_name.replace('.', os.path.sep) + '.py'
        ext = Extension(ext_name, [ext_path], include_dirs=['.'])
        ext.cython_directives = {'language_level': "3"}
        return ext
    extensions = map(lambda x: make_extension(x), ext_names)
    return list(extensions)
 
# 对加密后的py,pyc和c文件进行清除
class CleanCode(object):

    def clean_build(self, distribution):
        clean_command = clean(distribution)
        clean_command.all = True
        clean_command.finalize_options()
        clean_command.run()
    def delete(self, root, exts):
        src_files = load_files(root, exts=exts)
        for source_file in src_files:
            if os.path.basename(source_file):
                os.remove(source_file)
        
    def clean_pro(self, root):
        self.delete(root, exts=("pyd", "pyc", "c", "so"))
         
    def delete_source_code(self, root):
        self.delete(root, exts=("py", "c")) 
        
 
MODULE_NAME = "mobilenet_test"   # 给项目名字
root = "src" 
# 继承Cython的build_ext类  
class CustomBuildExt(build_ext, CleanCode):
  
    def run(self):
        self.clean_pro(root)
        build_ext.run(self)
        self.clean_build(self.distribution)
        self.delete_source_code(root)  # 清理源代码,只保留编译后文件
 
setup(
    name=MODULE_NAME,
    packages=get_packages(root),
    ext_modules=get_extensions(root),
    cmdclass={'build_ext': CustomBuildExt}   # 自定义的CustomBuildExt
)

注意第73行代码定义了需要编译的python代码根目录。执行上面代码后,会自动清理掉原始的python源码,读者需要做好备份。如果读者想保留原始python代码,将第81行注释即可。具体执行以上代码命令为:

python compile.py build_ext --inplace

执行后,项目结构如下:

编译后的算法项目结构
编译后的算法代码是二进制汇编代码,已经无法反编译:
编译后的算法库文件

原始的算法代码无需任何修改,继续执行test.py文件:

python test.py

输出如下:

404 0.8282396

可以看到输出内容一模一样

3 获取源码

  1. 关注公众号:Python学习实战
  2. 公众号聊天界面回复:Cython示例,获取完整源码。

如果您觉得本文有帮助,辛苦您点个不需花钱的赞,您的举手之劳将对我提供了无限的写作动力! 也欢迎关注我的公众号:Python学习实战, 第一时间获取最新文章。
关注【Python学习实战】

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1802364.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

对待谷歌百度等搜索引擎的正确方式

对待百度、谷歌等搜索引擎的方式是,你要站在搜索引擎之上,保持自己的独立思想和意见。 当谷歌宣布他们将会根据一个名为“Alphabet”的新控股公司来进行业务调整时,在科技界引起了一片恐慌之声。 永远不要说这是一个公司一直在做的事情。不…

【Linux】深入解析动静态库:原理、制作、使用与动态链接机制

文章目录 前言:1. 什么是动静态库2. 动静态库的制作和使用3. 动态库的查找问题4. 理解动态库的加载4.1. 站在系统的角度理解4.2. 编址、可执行程序4.3. 动态库动态链接和加载问题 总结: 前言: 在软件开发中,动静态库是两种重要的…

【栈】1106. 解析布尔表达式

本文涉及知识点 栈 LeetCode 1106. 解析布尔表达式 布尔表达式 是计算结果不是 true 就是 false 的表达式。有效的表达式需遵循以下约定: ‘t’,运算结果为 true ‘f’,运算结果为 false ‘!(subExpr)’,运算过程为对内部表达式…

2024年【R2移动式压力容器充装】考试技巧及R2移动式压力容器充装复审考试

题库来源:安全生产模拟考试一点通公众号小程序 R2移动式压力容器充装考试技巧参考答案及R2移动式压力容器充装考试试题解析是安全生产模拟考试一点通题库老师及R2移动式压力容器充装操作证已考过的学员汇总,相对有效帮助R2移动式压力容器充装复审考试学…

ubuntu系统 kubeadm方式搭建k8s集群

服务器环境与要求: 三台服务器 k8s-master01 192.168.26.130 操作系统: Ubuntu20.04 k8s-woker01 192.168.26.140 操作系统: Ubuntu20.04 k8s-woker02 192.168.26.150 操作系统: Ubuntu20.04 最低配置:2…

【启程Golang之旅】协程和管道操作

欢迎来到Golang的世界!在当今快节奏的软件开发领域,选择一种高效、简洁的编程语言至关重要。而在这方面,Golang(又称Go)无疑是一个备受瞩目的选择。在本文中,带领您探索Golang的世界,一步步地了…

【ARM Cache 与 MMU 系列文章 7.6 -- ARMv8 MMU 配置 寄存器使用介绍】

请阅读【ARM Cache 及 MMU/MPU 系列文章专栏导读】 及【嵌入式开发学习必备专栏】 文章目录 MMU 转换控制寄存器 TCR_ELxTCR_ELx 概览TCR_ELx 寄存器字段详解TCR 使用示例Normal MemoryCacheableShareability MMU 内存属性寄存器 MAIR_ELxMAIR_ELx 寄存器结构内存属性字段Devic…

人工智能在【肿瘤生物标志物】领域的最新研究进展|顶刊速递·24-06-08

小罗碎碎念 本期文献速递的主题是——人工智能在“肿瘤生物标志物”领域的最新研究进展。 重点关注 今天推荐的6篇文献中,第二篇和第三篇是小罗最喜欢的,因为对于临床来说,比较具有实际意义,也和自己的想法很契合。 尤其是第三篇…

华安保险:核心系统分布式升级,提升保费规模处理能力2-3倍 | OceanBase企业案例

在3月20日的2024 OceanBase数据库城市行的活动中,安保险信息科技部总经理王在平发表了以“保险行业核心业务系统分布式架构实践”为主题的演讲。本文为该演讲的精彩回顾。 早在2019年,华安保险便开始与OceanBase接触,并着手进行数据库的升级…

uniapp自定义的下面导航

uniapp自定义的下面导航 看看效果图片吧 文章目录 uniapp自定义的下面导航 看看效果图片吧 ![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/6aa0e964741d4dd3a58f4e86c4bf3247.png) 前言一、写组件、我这里就没有写组件了直接写了一个页面?总结 前言 在…

ubuntu使用docker安装openwrt

系统:ubuntu24.04 架构:x86 1. 安装docker 1.1 离线安装 docker下载地址 根据系统版本,依次下载最新的三个关于docker的软件包 container.io(注意后缀版本顺序)docker-ce-clidocker-ce 然后再ubuntu系统中依次按顺…

javaweb学习(day14-ThreadLocal文件上传下载)

一、线程数据共享和安全 -ThreadLocal 1 什么是 ThreadLocal ThreadLocal 的作用,可以实现在同一个线程数据共享, 从而解决多线程数据安全问题. ThreadLocal 可以给当前线程关联一个数据(普通变量、对象、数组)set 方法 [源码!] ThreadLocal 可以像 Map 一样存取数…

量化交易:Miniqmt获取可转债数据和交易python代码

哈喽,大家好,我是木头左! 低风险资产除了国债外,还有可转债,兼容有高收益的股性和低风险的债性,号称“下有保底,上不封顶”。 🔍 可转债:金融市场的双面娇娃 可转债&am…

web学习笔记(六十五)

目录 1. Hash模式和History模式 2. 导航守卫 3. 路由元信息 4.路由懒加载 1. Hash模式和History模式 Hash模式(哈希模式)和History模式(历史模式)是匹配路由的两种模式,一般默认配置Hash模式,可以在in…

软件架构x86 、 x86_64、 arm64、aarch64

看系统信息: 大多数Linux发行版都提供如 uname -a命令 arch命令用于显示当前主机的硬件架构类型。 例如 下面的是Kylin Linux Advanced Server for Kunpeng V10 操作系统 (鲲鹏处理器是华为在2019年1月向业界发布的高性能数据中心处理器 ) 下面这个是 ubuntu 18.04.6 …

【AI论文与新生技术】Follow-Your-Emoji:精细可控且富有表现力的自由式人像动画技术

我们提出了 Follow-Your-Emoji,这是一种基于扩散的肖像动画框架,它使用目标地标序列对参考肖像进行动画处理。肖像动画的主要挑战是保留参考肖像的身份并将目标表情转移到该肖像,同时保持时间一致性和保真度。为了应对这些挑战,Fo…

四、利用启发式算法进行特定数据集的残差网络结构搜索【框架+源码】

背景:工作之后干的事情跟算法关联甚少,整理下读书期间的负责和参与的work,再熟悉学习下。 边熟悉边整理喽~ CV Tradictional workCV AI based work机械臂视觉抓取项目机器学习全流程 Pipeline训练平台OCR生产线喷码识别三维重建(SfM)ROS机器人…

SpringBoot Elasticsearch06-以黑马商场为例-黑马程序员学习笔记

黑马商城作为一个电商项目,商品的搜索肯定是访问频率最高的页面之一。目前搜索功能是基于数据库的模糊搜索来实现的,存在很多问题。 首先,查询效率较低。 由于数据库模糊查询不走索引,在数据量较大的时候,查询性能很…

学习笔记——路由网络基础——汇总静态路由

4、汇总静态路由 (1)定义 静态路由汇总:多条静态路由都使用相同的送出接口或下一跳 IP 地址。(将多条路由汇总成一条路由表示) (2)目的 1.减少路由条目数量,减小路由表,加快查表速度 2.增加网络稳定性 (3)路由黑洞以及路由环路的产生…

旧衣回收小程序开发,轻松回收旧衣物

随着环保理念的增强,回收市场得到了快速发展,吸引了不少年轻人进入到市场中创业。除了传统的废品回收外,旧衣回收也受到了大众的重视,市场规模迅速扩大,大众浪费的衣物也获得了归处。 目前旧衣回收的方式主要是线上与…