網上說的將python代碼,通過Cython打包成pyd的教程挺多,好處也多,主要有兩個:
1.隱藏代碼
2.加速運行速度
補充兩點:
1.打包腳本配置
__build__.py
1 from distutils.core import setup 2 from Cython.Build import cythonize 3 import filemanager, os 4 5 filelist = [] 6 folders = [".\\"] # ".\\utils", 7 excludes = [ "__init__", "__build__", "u3dNameRes" ] 8 9 for rootpath in folders: 10 11 alllist = filemanager.getFileList(rootpath, ".py") 12 for file in alllist: 13 if not any(ex in file for ex in excludes): 14 filelist.append(file) 15 16 setup( 17 name = 'any words.....', 18 ext_modules = cythonize(filelist, compiler_directives = {'language_level': 2}), 19 )
filemanager.getFileList 是工具類,用來獲取某目錄下,指定后綴的文件列表
make.bat
1 @echo off 2 set libname=u3dnamedres 3 rem if exist build ( rd build /s /q ) 4 python __build__.py build_ext --inplace 5 xcopy %libname% .\ /s /e /y 6 rd %libname% /s /q 7 pyinstaller -F u3dNameRes.py 8 del *.pyd /s /q 9 del *.c /s /q
第4行是生成pyd文件
這里有個特別要注意的點,就是不同目錄下的py文件,一定要在目錄下加上__init__.py,然后在里面引用你的py文件。
引用的路徑只需要寫到模塊下的目錄,不要把模塊的名字也加到最前面去。
不然,等會生成的pyd文件會變成在根目錄下,導致編譯exe的時候,找不到pyd文件。這點非常重要。
2.加載的兩種方式
1)直接引用
直接引用就是跟平時寫代碼的一樣,直接import .... 或者是 from xxxx import .... 又或者是import xxxx as yyy即可
2)外部加載
獲取查找文件的方式,並配合pkgutil.iter_modules,把pyd加載到內存里面。
1 def loadpys(dirs): 2 if isinstance(dirs, str): 3 dirs = [dirs] 4 5 if os.getcwd() not in sys.path: 6 sys.path.append(os.getcwd()) 7 for path in dirs: 8 prefix = path + "." 9 roots = [ "%s%s%s" % (p, os.sep, path) for p in sys.path] 10 for _importer, modname, _ispkg in pkgutil.iter_modules(roots, prefix): 11 try: 12 if _ispkg: 13 module = __import__(modname, fromlist = ["__init__"]) 14 else: 15 module = __import__(modname, fromlist = True) 16 except Exception as e: 17 raise Exception("import failed %s" % modname) 18 else: 19 yield module, modname
這方法同樣適用於加載exe外部的pyd文件。
另外,如果說是外部加載的pyd,要在pyinstaller打包的時候,也打進exe的話,需要進行以下步驟:
1.先跑一遍pyinstaller -F xxxx.py,生成 xxxx.spec
2.然后修改xxxx.spec,把要打包進去的pyd文件,添加到配置datas=[('*.pyd', '.\\proxy\\')]
3.然后再生成打包,用命令 pyinstaller -F xxxx.spec