由於項目的保密性需求,對已開發完成的項目需要進行加密處理,本文給出兩種方法。
加密py代碼,雖然編譯為pyc作用不大(很容易被反編譯出來源碼),但還是有一定加密的效果,如果項目比較時間緊,可以用此方法應急處理。
python -m compileall -f -q -b "py文件夾"
該命令會把目錄下的py文件都會生成相應的pyc文件
然後執行以下命令,刪除掉py文件,只保留pyc文件
find . -name "*.py" -type f -print -exec rm -rf { } \;
最後執行運行pyc文件就可以了
如: python ****.pyc
注意:此方法加密與使用的python版本要一致,否則會報錯。即運行 python -m compileall -f -q -b "py文件夾"
與 python ****.pyc
的版本要保持一致。
pip3 install Cython sudo apt-get update sudo apt-get install python-devel sudo apt-get install gcc
填寫如下內容:
#-* -coding: UTF-8 -* - """ 執行前提: 系統安裝python-devel 和 gcc Python安裝cython 編譯某個文件夾: python py2so.py BigoModel 生成結果: 目錄 build 下 生成完成後: 啟動文件還需要py/pyc擔當,須將啟動的py/pyc拷貝到編譯目錄並刪除so文件 """ import sys, os, shutil, time from distutils.core import setup from Cython.Build import cythonize starttime = time.time() setupfile= os.path.join(os.path.abspath('.'), __file__) def getpy(basepath=os.path.abspath('.'), parentpath='', name='', build_dir="build", excepts=(), copyOther=False, delC=False): """ 獲取py文件的路徑 :param basepath: 根路徑 :param parentpath: 父路徑 :param name: 文件/夾 :param excepts: 排除文件 :param copy: 是否copy其他文件 :return: py文件的迭代器 """ fullpath = os.path.join(basepath, parentpath, name) for fname in os.listdir(fullpath): ffile = os.path.join(fullpath, fname) if os.path.isdir(ffile) and ffile != os.path.join(basepath, build_dir) and not fname.startswith('.'): for f in getpy(basepath, os.path.join(parentpath, name), fname, build_dir, excepts, copyOther, delC): yield f elif os.path.isfile(ffile): # print("\t", basepath, parentpath, name, ffile) ext = os.path.splitext(fname)[1] if ext == ".c": if delC and os.stat(ffile).st_mtime > starttime: os.remove(ffile) elif ffile not in excepts and ext not in('.pyc', '.pyx'): # print("\t\t", basepath, parentpath, name, ffile) if ext in('.py', '.pyx') and not fname.startswith('__'): yield os.path.join(parentpath, name, fname) elif copyOther: dstdir = os.path.join(basepath, build_dir, parentpath, name) if not os.path.isdir(dstdir): os.makedirs(dstdir) shutil.copyfile(ffile, os.path.join(dstdir, fname)) else: pass if __name__ == "__main__": currdir = os.path.abspath('.') parentpath = sys.argv[1] if len(sys.argv)>1 else "." currdir, parentpath = os.path.split(currdir if parentpath == "." else os.path.abspath(parentpath)) build_dir = os.path.join(parentpath, "build") build_tmp_dir = os.path.join(build_dir, "temp") print("start:", currdir, parentpath, build_dir) os.chdir(currdir) try: #獲取py列表 module_list = list(getpy(basepath=currdir,parentpath=parentpath, build_dir=build_dir, excepts=(setupfile))) print(module_list) setup(ext_modules = cythonize(module_list),script_args=["build_ext", "-b", build_dir, "-t", build_tmp_dir]) module_list = list(getpy(basepath=currdir, parentpath=parentpath, build_dir=build_dir, excepts=(setupfile), copyOther=True)) except Exception as ex: print("error! ", ex) finally: print("cleaning...") module_list = list(getpy(basepath=currdir, parentpath=parentpath, build_dir=build_dir, excepts=(setupfile), delC=True)) if os.path.exists(build_tmp_dir): shutil.rmtree(build_tmp_dir) print("complate! time:", time.time()-starttime, 's')
python py2so.py project_dir_path
運行結束後, project_dir_path
會生成一個 build
文件夾,將該文件夾下的.os文件全部移動到被加密的文件夾對應的位置,刪除原文件夾下的py文件,若為啟動文件,建議保留,可通過啟動文件來運行程序。
將py文件編譯成pyc:
Python 標准庫中提供了一個名為 compileall
的庫,可以輕松地進行編譯。簡單方便,提高了一點源碼破解門檻
平台兼容性好, py
能在哪裡運行, pyc
就能在哪裡運行。但是有現成的反編譯工具( python-uncompyle6
),破解成本低。建議在項目時間緊,應急時使用。
將py轉化成so文件:
Cython方法加密就是將 py
文件轉為 so
文件,用 so
文件替換 py
文件,執行速率會比python快一些,但是偶爾會遇到部分代碼不好使,只能針對進行測試,將失效的不進行加密或者采取其他方式加密。加密效果好,不易被反編譯,但是對於項目需要一步步測試。