参考文档:
https://github.com/cython/cython
https://zhuanlan.zhihu.com/p/54296517
Cython介绍
Cython是一个类似于Python的编程语言,它是基于Python语言的扩展和优化。Cython语言是一种静态类型语言,同时也支持Python的动态类型特性,Cython代码会被转换成C语言代码,再编译成机器码,因此其执行速度比Python要快。
虽然Cython 的主要目的是带来性能的提升,但是基于它的原理:将 .py/.pyx 编译为 .c 文件,再将 .c 文件编译为 .so(Unix) 或 .pyd(Windows),其带来的另一个好处就是难以破解。但需要注意的是,cython本质上并非提供加密功能,而是通过编译成二进制文件后,提高他人阅读核心代码的难度,使用此方法加密代码还要注意代码安全。
方法
1)编写 setup.py:
可根据cython官方文档的指引,对您的代码进行编译。以下代码可供参考:
此脚本将会找到当前目录下所有含__init__.py文件的目录,并对他们进行编译,并在原地生成.so文件。
#encoding=utf-8fromsetuptoolsimportsetup, find_packagesfromsetuptools.extensionimportExtensionfromCython.BuildimportcythonizefromCython.Distutilsimportbuild_extfrompathlibimportPathimportshutilimportsys, os# some global variable, don't change them if you don't know what they meanmy_build_dir="build"classMyBuildExt(build_ext): defrun(self): build_ext.run(self) build_dir=Path(self.build_lib) root_dir=Path(__file__).parenttarget_dir=build_dirifnotself.inplaceelseroot_dirformoduleinmy_packages: module=module.replace(".","/") module_path=Path(module) print(">>find modeule path:"+str(module_path)) self.copy_file(module_path/'__init__.py', root_dir, target_dir) self.copy_file(module_path/'__main__.py', root_dir, target_dir) forpinPath('.').iterdir(): ifp.is_file() andp.suffixnotin [".py", ".pyc"] andp.namenotinexclude_list: self.copy_file(p, root_dir, target_dir) print("copy end") defcopy_file(self, path, source_dir, destination_dir): ifnot (source_dir/path).exists(): returnshutil.copyfile(str(source_dir/path), str(destination_dir/path)) deffind_scrips(): scrips_list= [] forpinPath('.').iterdir(): ifp.is_file() and (p.namenotinexclude_list): ifp.suffixin [".py"] and (notp.name.startswith(".")): scrips_list.append(p.name) print("find scrips:") print(scrips_list) print(exclude_list) returnscrips_listif__name__=="__main__": my_project_name="test"my_clang="gcc "ifos.path.isdir(my_build_dir): print("Exist build dir, auto remove") shutil.rmtree(my_build_dir) print("===============start=================") exclude_list= ["setup.py", ".DS_Store"] os.environ["CC"]=my_clangmy_packages=find_packages() print("packages:") print(my_packages) ext=[] #找到所有的packageformoduleinmy_packages: module=module.replace(".","/") ext.append(Extension(module+".*", [module+"/*.py"])) #找到根目录下的脚本ext.extend(find_scrips()) print("Extension:") print(ext) setup( name=my_project_name, ext_modules=cythonize( ext, build_dir=my_build_dir, compiler_directives=dict( always_allow_keywords=True )), cmdclass=dict( build_ext=MyBuildExt ), packages=find_packages(where=".") ) print("===============end=================")
2)编译为 .c,再进一步编译为 .so 或 .pyd:
python setup.py build_ext --inplace
3)删除python源码,通过.so的方式进行执行:
find . -name'*py[c~]'-delete
4)编写启动脚本,执行过程中调用启动脚本:
from real_main import main import sys if __name__ =='__main__': main(sys.argv[1:])
注意事项
Cython 源代码的语法是 Python语法的一个超集,也就是说,任何可以在 Python 中使用的语法,也可以在 Cython 中使用。但是,以下几种 Python语法在 Cython 中是不支持的:
1.动态类型变量声明:在 Cython 中,变量必须是静态类型,需要在声明时指定数据类型。
2.不支持 eval() 函数和 exec语句:因为 Cython 是一种编译型语言,无法像 Python一样动态生成代码。
3.不支持生成器表达式和列表推导式:Cython 中不能直接使用生成器表达式和列表推导式,但是可以使用类似于 Python 中的 for 循环语句来达到相同的效果。
4.不支持一些 Python 内置函数:例如 zip(), filter(), map() 等,但是 Cython 提供了自己的实现,用于替代这些函数。
5.不支持 slots 特殊变量:Cython 中不支持 slots 特殊变量来限制类的属性,但是可以使用 cdef class 来实现类的属性限制。
6.不支持一些 Python 模块和库:例如 asyncio, logging 等,因为这些模块和库在 Cython 中不可用。
7.不支持 Python 的全局解释器锁(GIL):Cython 中没有 GIL,因此可以使用 Python 的多线程模块来实现并发编程。