py文件批量编译,py批量转pyd,PyCharm设置py转pyd功能


转载自 【编程技巧】py文件批量编译,py批量转pyd,PyCharm设置py转pyd功能

python文件*.py都是明文,很难对代码进行加密。而python -m py_compile xxx.py的编译操作只能编译成pyc,pyc是很容易反编译的。
如果想彻底编译成二进制文件,必须用到Cython编译成pyd二进制文件。
但是使用Cython处理比较麻烦,要编写setup.py等很多设置。

本文的代码可以自动对单个py文件、目录中的所有文件(包含子目录里的py)进行自动编译,一键操作,非常便捷。还可以在集成环境PyCharm中进行一键操作。

一、运行代码

话不多说,先上代码。
参数说明请详细看注释,注释写的很全面。
注意首先Python环境要先安装cython模块:
pip install cython

如下是主代码,文件名:py2pyd.py

# coding=utf-8
"""
Python批量编译程序
命令行参数说明:
all:对目录及子目录下的所有py文件进行编译
one:对单个py文件进行编译
del:编译完删除py文件。此操作无法恢复、慎用!!!
nodel:编译完不删除py文件
例子:
python py2pyd.py all del D:\PYTHON\toPYD\test
python py2pyd.py one nodel D:\PYTHON\toPYD\test\mycode.py
"""
import os, shutil, time, sys, glob

try:
    from setuptools import setup  # 检测是否安装了cython
except:
    print("\n请先安装cython模块:pip install cython\n"); sys.exit()

python_path = "D:/work/dcc_scripts/python310/python.exe"


def py2pyd(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:  # 自动生成单独的setup.py文件
        write_str = """
# coding=utf-8     
from Cython.Build import cythonize
from setuptools import setup, Extension, find_packages
from setuptools.command.build_ext import build_ext as _build_ext
import os
class build_ext(_build_ext):
    def build_extension(self, ext):
        original_get_ext_fullpath = self.get_ext_fullpath

        def override_get_ext_fullpath(ext_name):
            filename = original_get_ext_fullpath(ext_name)
            return os.path.basename(filename)

        self.get_ext_fullpath = override_get_ext_fullpath
        _build_ext.build_extension(self, ext)
    
    def copy_extensions_to_source(self):
        pass
        
setup(
name='{}',
ext_modules=cythonize('{}', compiler_directives={{'language_level': '3'}}),
author = 'xinglian',
author_email = 'beimingxinglian@gmail.com',
cmdclass={{'build_ext': build_ext}}
)
"""
        write_str = write_str.format(file_path[:-3], file_path)
        f.write(write_str)

    print('"{}" {}/setup.py build_ext --inplace'.format(python_path, folder_path))
    os.system('"{}" {}/setup.py build_ext --inplace'.format(python_path, folder_path))  # py编译开始

    filename = file_path.split('.py')[0]  # 文件名
    pyd_name = '%s\\%s.pyd' % (folder_path, filename)  # pyd文件名
    if os.path.exists(pyd_name):
        os.remove(pyd_name)  # 删除老的pyd

    amd64_pyd = glob.glob(filename + "*.pyd")  # 获取pyd文件的全名,类似***.cp38-win_amd64.pyd
    if not amd64_pyd:
        print(filename + "生成失败")
        return
    print("生成了PYD:" + amd64_pyd[0])

    os.rename(amd64_pyd[0], pyd_name)  # 改名字,删除多余的cp38-win_amd64.等
    os.remove('%s.c' % filename)  # 删除临时文件
    build_folder_path = os.path.join(folder_path, 'build')
    shutil.rmtree(build_folder_path)  # 删除掉生成的build文件夹
    os.remove('setup.py')  # 删除掉生成的setup.py
    if del_py == 'del':  # 删除py源文件,无法恢复,慎用!
        os.remove(file_path)


def get_all_file(path):  # 遍历此目录下的所有py文件,包含子目录里的py
    for root, dirs, files in os.walk(path):
        for name in files:
            if name.endswith(".py"):
                file_path = os.path.join(root, name)
                py2pyd(file_path)


if len(sys.argv) <= 3:  # 判断命令行参数是否合法
    print("\n命令行参数错误...\n");
    sys.exit()

one_all, del_py, paths = sys.argv[1:4]  # 获取命令行参数

if one_all == 'one':
    py2pyd(paths)
else:
    get_all_file(paths)

批处理测试文件:

::Python批量编译程序
::命令行参数说明:
::all:对目录及子目录下的所有py文件进行编译
::one:对单个py文件进行编译
::del:编译完删除py文件。此操作无法恢复、慎用!!!
::nodel:编译完不删除py文件
::例子:
::python py2pyd.py all del D:\PYTHON\toPYD\test
::python py2pyd.py one nodel D:\PYTHON\toPYD\test\mycode.py

python py2pyd.py all del D:\PYTHON\toPYD\test
python py2pyd.py one nodel D:\PYTHON\toPYD\test\ianx6.py
pause

二、PyCharm的自动设置

在CMD里用命令行运行py2pyd,可能比较麻烦。如果可以在PyCharm集成环境里直接编译那就太好了。如下设置可以实现。

依次点击:PyCharm->文件->设置->工具->外部工具,点击“+”,进入编辑窗口

image-20240523105000676

单个文件

批量处理

  • 程序: python.exe

  • 实参:

    • 单个:py2pyd.py one nodel $FileDir$\$FileName$
    • 批量:py2pyd.py all nodel $FileDir$

第一个参数 py2pyd.py的路径要自己修改成实际路径

如果你想编译后把py文件删除,只保留pyd文件,把nodel改成del即可,慎用!删除后不可恢复,回收站也没有的啊!


评论
  目录