批量编译生成python的pyd文件

我们编写的程序源代码,或者下一个小的脚本文件需要对外发布时,我们有时候不想让别人能轻易地看到我们的源码,可以将其编译成pyd形式地进行外发,pyd相对于pyc和pyo编译文件,他们两种文件形式差不多,也很容易被反编译,pyd格式是D语言(C/C++综合进化版本)生成的二进制文件,实际也是DLL文件,这种格式文件目前好像是没有可以反编译的消息,只能反汇编。这种文件区别于打包成exe是它生成的pyd文件还可以是原来项目的目录结构,对于项目开发者来说释放出去之后出现问题也方便定位。废话多说,上代码比较。

以获取当前工作目录的代码为例,我们对比一下pyc文件和pyd文件的区别

源码 假定文件是current_path.py

1 import time
2 import os
3 ​
4 while 1:
5   time.sleep(1)
6   print(os.getcwd())

在该文件的目录下打开python解释器执行

批量编译生成python的pyd文件

 

 

 可以看到在当前目录下生成一个__pychache__的文件夹,打开会有一个同名的pyc文件

批量编译生成python的pyd文件

 

 

 打开之后,

批量编译生成python的pyd文件

 

 

 还是多少能看到点源码的,这个就违背了不想让人看到源码的初衷了,我们再来看下生成的pyd文件,

批量编译生成python的pyd文件

 

 

 

这就很nice了。下面介绍具体方法:

1、安装Cython,python下很简单,pip3 install cython 即可

2、准备源文件、即上面的current_path.py

3、准备打包文件 set_up.py 内容如下

from distutils.core import setup
from Cython.Build import cythonize
​
setup(ext_modules=cythonize("set_up.py"))

4、在当前目录下执行

python set_up.py build_ext --inplace

5、报错  Unable to find vcvarsall.bat

解决办法 安装Visual studio 官网下载社区版即可安装时选择Python开发进行安装(下图是找的,自己安装的时候忘记截图了,懒得截了)

批量编译生成python的pyd文件

 

 

 批量编译生成python的pyd文件

批量编译生成python的pyd文件

python setup.py build_ext --inplace

在超过二级目录的时候会额外多一级目录,目前还没有好的办法解决,希望看到这例的读者能提供一个好的建议。再有就是如果项目中出现了同名的set_up.py时,要记得单独编译一下。

批量编译生成python的pyd文件

 

 

 批量编译生成python的pyd文件

 

将其重命名,去掉 cp37-win_amd64.,将其移动到源文件位置删除源文件,就可以使用了,但是不是直接执行该文件,而是去另外一个文件例去导入该文件的函数或者类,执行另外一个py文件,这时候就执行成功了。跟正常的源文件一样,这时候就满足了需求。

上述是单个打包成pyd文件,但是批量打包的话这样做很难受,我看到的只是批量生成pyc文件的命令,但是没有批量生成pyd文件的命令,于是自己就写了一段程序供大家参考,代码如下 create_pyd_file.py

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# @time: 2021/5/26 14:17
# @File: create_pyd_file.py
import os
import shutil
import time
import sys
​
​
def func(path):
    folder_path = os.path.dirname(path)
    file_path = os.path.split(path)[1]
    os.chdir(folder_path)
    with open('setup.py', 'w') as f:
        f.write('from setuptools import setup\n')
        f.write('from Cython.Build import cythonize\n')
        f.write('setup(\n')
        f.write("name='test',\n")
        f.write("ext_modules=cythonize('%s')\n" % file_path)
        f.write(")\n")
    os.system('python setup.py build_ext --inplace')
    filename = file_path.split('.py')[0]
    time.sleep(2)
    # 这里的cp37-win_amd64需要注意一下,这个是依据python解释器类型以及windows版本生成的,建议是单个生成一个pyd文件然后相应修改一下
    os.rename('%s\\%s.cp37-win_amd64.pyd' % (folder_path, filename), '%s\\%s.pyd' % (folder_path, filename))
    # 这个是删除py源文件,测试的时候可以先注释掉查看效果
    os.remove('%s.c' % filename)
    build_folder_path = os.path.join(folder_path, 'build')
    # 删除掉生成的build文件夹
    shutil.rmtree(build_folder_path)
    os.remove('setup.py')
    os.remove(file_path)
​
​
def get_all_file(path):
    for root, dirs, files in os.walk(path):
        for name in files:
            if name.endswith(".py"):
                file_path = os.path.join(root, name)
                func(file_path)
​
​
paths = sys.argv[1]
get_all_file(paths)
​

调用的方法是在该文件当前路径下执行 加上项目的绝对路径 比如

python create_pyd_file.py D:\python_demo\demo

测试的时候在windows以及ubuntu上二级目录都可以编译成pyd文件并替换到原来的位置 现在有点问题的就是再深层级的目录就出现问题了,原因是这条命令

更多精彩,可以关注楼主的公众号,

批量编译生成python的pyd文件

最全面的django面试题总结: 回复django面试题即可获取, pycharm供给激活压缩包, 回复pycharm破解包即可获取,破解步骤在我的这一篇博客(点我直达)已经破解百次, 屡试不爽.

以及其他楼主精心打造的原创文章,欢迎各位来访.

 

上一篇:带着兴奋与敬畏前行


下一篇:编译 python 代码