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))