网上说的将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