基于Cython和内置distutils库,实现python源码加密(非混淆模式)
起因
python本身只能做混淆,不能加密,多年的商业软件开发导致有某种“洁癖”:欲将py编译打包
尝试
- pyinstaller原理是freeze打包pyc文件,利用工具可完美逆行出源码
- 各种混淆脚本,版本兼容很差,配置繁琐
- cython 常规使用只能编译单个特殊模块
解决
反复尝试摸索后,还是利用了cython和distutils库,自动化识别并转换py到c源码并编译,放出源码供大家参考
"""
利用cython和distutils编译py到pyd[so] 注意安装cython及本地平台对应编译器
http://flywuya.cnblogs.com/
"""
import os
import shutil
from distutils.core import setup
from distutils.command.build_ext import build_ext
from Cython.Build import cythonize
BUILD_CONFIG = {
'SupportExt': ['.py', '.pyx'],
'CopyOnlyFile': ['__main__.py', '__init__.py'],
'CopyOnlyDir': ['assets'],
'IgnoreDir': ['dist', 'build', '__pycache__'],
}
def copy_tree(src, dst):
""" not like shutil.copytree, dst can be exists """
assert os.path.exists(src)
assert os.path.isdir(src)
os.makedirs(dst, exist_ok=True)
for fn in os.listdir(src):
s = os.path.join(src, fn)
t = os.path.join(dst, fn)
if os.path.isfile(s):
shutil.copy2(s, t)
elif os.path.isdir(s):
copy_tree(s, t)
def build_module(source_file, dst_dir, tmp_dir):
""" cythonize && build ext """
assert os.path.isfile(source_file)
assert not os.path.isabs(source_file)
assert os.path.exists(dst_dir)
os.makedirs(tmp_dir, exist_ok=True)
build_cython = os.path.join(tmp_dir, 'build.cython')
build_temp = os.path.join(tmp_dir, 'build.temp')
build_lib = dst_dir
ext_modules = cythonize(
source_file,
build_dir=build_cython,
language_level=3,
)
class build_here(build_ext):
def initialize_options(self):
super().initialize_options()
self.build_temp = build_temp
self.build_lib = build_lib
setup(
ext_modules=ext_modules,
script_args=['build_ext'],
cmdclass=dict(build_ext=build_here)
)
def build_modules(source_dir, dst_dir, tmp_dir):
""" scan && build modules in source_dir """
assert os.path.exists(source_dir)
assert not os.path.isabs(source_dir)
assert not os.path.isabs(dst_dir)
os.makedirs(dst_dir, exist_ok=True)
for root, dirs, files in os.walk(source_dir):
rel_pth = root[len(source_dir)+1:]
for ignore in BUILD_CONFIG['IgnoreDir']:
if ignore in dirs:
dirs.remove(ignore)
for dn in dirs:
if dn in BUILD_CONFIG['CopyOnlyDir']:
copy_tree(
os.path.join(root, dn),
os.path.join(dst_dir, rel_pth, dn)
)
dirs.remove(dn)
for fn in files:
_, ext = os.path.splitext(fn)
os.makedirs(
os.path.join(dst_dir, rel_pth),
exist_ok=True
)
if fn in BUILD_CONFIG['CopyOnlyFile']:
shutil.copy2(
os.path.join(root, fn),
os.path.join(dst_dir, rel_pth, fn)
)
elif ext.lower() in BUILD_CONFIG['SupportExt']:
build_module(
os.path.join(root, fn),
dst_dir,
os.path.join(tmp_dir, rel_pth),
)
else:
shutil.copy2(
os.path.join(root, fn),
os.path.join(dst_dir, rel_pth, fn)
)
if __name__ == "__main__":
# 这里填写要编译的目录
tasks = [
'app',
]
others = [
'requirements.txt',
'packages',
]
BUILD_CONFIG['CopyOnlyFile'].extend(['settings.py'])
for task in tasks:
build_modules(
task,
os.path.join('dist', task),
os.path.join('build', task),
)
for other in others:
if os.path.isfile(other):
bn = os.path.basename(other)
shutil.copy2(other, os.path.join('dist', bn))
elif os.path.isdir(other):
bn = os.path.basename(other)
copy_tree(other, os.path.join('dist', bn))
基于Cython和内置distutils库,实现python源码加密(非混淆模式)的更多相关文章
- 用内置的库turtle来画一朵花,python3
题目:用内置的库turtle来画一朵花 看了群主最后成像的图片,应该是循环了36次画方框,每次有10度的偏移. 当然不能提前看答案,自己试着写代码. 之前有用过海龟画图来画过五角星.奥运五环.围棋盘等 ...
- 查看python内部模块命令,内置函数,查看python已经安装的模块命令
查看python内部模块命令,内置函数,查看python已经安装的模块命令 可以用dir(modules) 或者用 pip list或者用 help('modules') 或者用 python -m ...
- 基于Zlib算法的流压缩、字符串压缩源码
原文:基于Zlib算法的流压缩.字符串压缩源码 Zlib.net官方源码demo中提供了压缩文件的源码算法.处于项目研发的需要,我需要对内存流进行压缩,由于zlib.net并无相关文字帮助只能自己看源 ...
- 基于Docker的TensorFlow机器学习框架搭建和实例源码解读
概述:基于Docker的TensorFlow机器学习框架搭建和实例源码解读,TensorFlow作为最火热的机器学习框架之一,Docker是的容器,可以很好的结合起来,为机器学习或者科研人员提供便捷的 ...
- 基于Ubuntu 14.04 LTS编译Android4.4.2源码
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/gobitan/article/details/24367439 基于Ubuntu 14.04 LTS ...
- Python源码剖析——01内建对象
<Python源码剖析>笔记 第一章:对象初识 对象是Python中的核心概念,面向对象中的"类"和"对象"在Python中的概念都为对象,具体分为 ...
- python 内置标准库socketserver模块的思考
socketserver模块简化了编写网络服务器的任务, 在很大程度上封装了一些操作, 你可以看成是事件驱动型的设计, 这很不错.它定义了两个最基本的类--服务器类 BaseServer, 请求处理类 ...
- 2.3 spring5源码系列---内置的后置处理器PostProcess加载源码
本文涉及主题 1. BeanFactoryPostProcessor调用过程源码剖析 2. 配置类的解析过程源码 3. 配置类@Configuration加与不加的区别 4. 重复beanName的覆 ...
- 基于vue实现一个简单的MVVM框架(源码分析)
不知不觉接触前端的时间已经过去半年了,越来越发觉对知识的学习不应该只停留在会用的层面,这在我学jQuery的一段时间后便有这样的体会. 虽然jQuery只是一个JS的代码库,只要会一些JS的基本操作学 ...
随机推荐
- Effective Java 中文版
始读于2014年8月2日10:15,整理完成于2014年8月20日23:14:42 一图一世界,<Effective Java >是Java领域大牛Joshua Bloch的获奖之作,去年 ...
- ramfs和tmpfs的区别
简介 ramfs和tmpfs是在内存上建立的文件系统(Filesystem).其优点是读写速度很快,但存在掉电丢失的风险.如果一个进程的性能瓶颈是硬盘的读写,那么可以考虑在ramfs或tmpfs上进行 ...
- 在Word 中撰写并发布到博客的帮助
目前大部分的博客作者在用Word写博客这件事情上都会遇到以下3个痛点: 1.所有博客平台关闭了文档发布接口,用户无法使用Word,Windows Live Writer等工具来发布博客.使用Word写 ...
- ios9出现的问题
升级后需要注意两个地方 1 在build Settings 搜索bitcode 设置成no 2 在info.plist里添加以下属性 程序中报错: App Transport Security ...
- ZOJ2388 Beat the Spread! 2017-04-16 19:18 91人阅读 评论(0) 收藏
Beat the Spread! Time Limit: 2 Seconds Memory Limit: 65536 KB Superbowl Sunday is nearly here. ...
- android事件分发
1). android对事件分发的顺序为:Activity--->PhoneWindow--->DecorView--->yourView; 2). android控件对事件处理的优 ...
- underscore arrays
1._.first():返回array(数组)的第一个元素.传递 n参数将返回数组中从第一个元素开始的n个元素 _.first = _.head = _.take = function(array, ...
- invoke方法
主要是为了类反射,这样你可以在不知道具体的类的情况下,根据配置的字符串去调用一个类的方法.在灵活编程的时候非常有用.很多框架代码都是这样去实现的.但是一般的编程,你是不需要这样做的,因为类都是你自己写 ...
- (zxing.net)一维码EAN 8的简介、实现与解码
一.简介 一维码EAN 8:属于国际标准条码,由8个数字组成,属EAN的简易编码形式(EAN缩短码).当包装面积小于120平方公分以下无法使用标准码时,可以申请使用缩短码. 依结构的不同,EAN条码可 ...
- ajaxfileupload插件上传图片功能,用MVC和aspx做后台各写了一个案例
HTML代码 和js 代码 @{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name=&quo ...