python打包编译成pyd或者_python源码保护之cython

学习交流而已,有不足之处还请各位大佬多多指点!!!

# 准备

项目需要,是在windows7上操作。python3.7,针对python项目,而非单个的python程序。

思路:先将py代码转成c代码,然后编译成pyd(window上是pyd,linux上是so)文件

安装cython:pip install cython

# 编译

**直接上源码**


  
  
  1. import sys, os, shutil, time
  2. from distutils.core import setup
  3. from Cython.Build import cythonize
  4. start_time = time.time()
  5. curr_dir = os.path.abspath( '.')
  6. parent_path = sys.argv[ 1] if len(sys.argv) > 1 else ""
  7. setup_file = __file__.replace( '/', '')
  8. build_dir = "build"
  9. build_tmp_dir = build_dir + "/temp"
  10. s = "# cython: language_level=3"
  11. def get_py(base_path=os.path.abspath('.'), parent_path='', excepts=()):
  12. """
  13. 获取py文件的路径
  14. :param base_path: 根路径
  15. :param parent_path: 父路径
  16. :param excepts: 排除文件
  17. :return: py文件的迭代器
  18. """
  19. full_path = os.path.join(base_path, parent_path, name)
  20. for filename in os.listdir(full_path):
  21. full_filename = os.path.join(full_path, filename)
  22. if os.path.isdir(full_filename) and filename != build_dir and not filename.startswith( '.'):
  23. for f in get_py(base_path, os.path.join(parent_path, name), filename, excepts, copyOther, delC):
  24. yield f
  25. elif os.path.isfile(full_filename):
  26. ext = os.path.splitext(filename)[ 1]
  27. if ext == ".c":
  28. if delC and os.stat(full_filename).st_mtime > start_time:
  29. os.remove(full_filename)
  30. elif full_filename not in excepts and os.path.splitext(filename)[ 1] not in ( '.pyc', '.pyx'):
  31. if os.path.splitext(filename)[ 1] in ( '.py', '.pyx') and not filename.startswith( '__'):
  32. path = os.path.join(parent_path, name, filename)
  33. yield path
  34. else:
  35. pass
  36. def pack_pyd():
  37. # 获取py列表
  38. module_list = list(get_py(base_path=curr_dir, parent_path=parent_path, excepts=(setup_file,)))
  39. try:
  40. setup(
  41. ext_modules=cythonize(module_list),
  42. script_args=[ "build_ext", "-b", build_dir, "-t", build_tmp_dir],
  43. )
  44. except Exception as ex:
  45. print( "error! ", str(ex))
  46. else:
  47. module_list = list(get_py(base_path=curr_dir, parent_path=parent_path, excepts=(setup_file,), copyOther= True))
  48. module_list = list(get_py(base_path=curr_dir, parent_path=parent_path, excepts=(setup_file,), delC= True))
  49. if os.path.exists(build_tmp_dir):
  50. shutil.rmtree(build_tmp_dir)
  51. print( "complate! time:", time.time() - start_time, 's')
  52. def delete_c(path='.', excepts=(setup_file,)):
  53. '''
  54. 删除编译过程中生成的.c文件
  55. :param path:
  56. :param excepts:
  57. :return:
  58. '''
  59. dirs = os.listdir(path)
  60. for dir in dirs:
  61. new_dir = os.path.join(path, dir)
  62. if os.path.isfile(new_dir):
  63. ext = os.path.splitext(new_dir)[ 1]
  64. if ext == '.c':
  65. os.remove(new_dir)
  66. elif os.path.isdir(new_dir):
  67. delete_c(new_dir)
  68. if __name__ == '__main__':
  69. try:
  70. pack_pyd()
  71. except Exception as e:
  72. print(str(e))
  73. finally:
  74. delete_c()

# 运行

在要打包的目录的同级目录下,创建setup.py,将上述代码复制到setup.py, 直接运行setup.py即可。

执行成功后,会出现一个build文件夹,其中包含有和要打包的项目结构一样的项目,和原项目不同的是,其中的py文件(除__init__外)均被打包成pyd文件,如此源码就被保护起来了。

ab6bdc404aa7fd25b8d3c5365af2e2ae.png

# 注意

windows上使用cython打包有很多坑

1. 出现“Unable to find vcvarsall.bat”错误

**方法:**

python3只能通过安装对应版本的vc++来解决

2. FutureWarning: Cython directive 'language_level' not set, using 2 for now (Py2)

**方法:**

在要打包的每个py文件中的第一行,添加如下语句,# cython: language_level=3

3. 编译后执行需要相同的python版本和编码

参考:

https://blog.csdn.net/qq_20154743/article/details/77891572

Python生成pyd文件 - 杨仕航的博客

可乐小埋酱:setup-cython(1):保护Python源码,提升执行性能

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值