python自己只能作混淆,不能加密,多年的商业软件开发致使有某种“洁癖”:欲将py编译打包python
反复尝试摸索后,仍是利用了cython和distutils库,自动化识别并转换py到c源码并编译,放出源码供你们参考app
""" 利用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))