python 自动打包pyd

需求:
经常要打包pyd,多个pyd一起打包,为了方便而自动化这项工作

实现代码:

import os
import shutil


def split_filename(file):
    file_path, file_name = os.path.split(file)
    file_sname, file_ext = os.path.splitext(file_name)
    return file_path, file_name, file_sname, file_ext

def pack_pyd_process(file, interpreter_path=r"D:\David\venvs\venv_anctest_ws_32\Scripts\python.exe", to_folder="."):
    if not interpreter_path.endswith("\python.exe"):
        interpreter_path = interpreter_path.rstrip("\\") + r"\python.exe"
    file_path, file_name, file_sname, file_ext = split_filename(file)

    # 1, 创建setup.py
    creat_setup_file(file, file_sname)

    # 2, 在命令行执行如下代码
    cmd_str = f"{interpreter_path} setup.py build_ext --inplace"
    # os_system(cmd_str)
    os_popen(cmd_str)

    # 3, 将当前文件夹下的 build 文件夹、pyd文件(所有)剪切到指定目标路径
    if os.path.abspath(to_folder) != os.path.abspath("."):

        # 将 build 文件夹剪切到指定目标路径
        try:
            shutil.move("build",
                        to_folder)  # shutil.Error: Destination path 'D:\David\rd\pack_del\build' already exists

        except shutil.Error as e:
            err_msg = f"e: {e}"
            print(f"{err_msg}")
            if "already exists" in err_msg:
                is_substitute = input("请问是否替换build?,输入y【Y】或者n【N】:")
                if is_substitute in ['y', 'Y']:
                    # 递归删除文件夹,即:删除非空文件夹;如果报错  OSError: [Errno 39] Directory not empty 则设置参数 ignore_errors
                    shutil.rmtree(os.path.join(to_folder, "build"), ignore_errors=True)
                    shutil.move("build", to_folder)
                elif is_substitute in ['n', 'N']:
                    pass

        # 将当前文件夹下的pyd文件(所有)剪切到指定目标路径
        files = os.listdir(".")
        pyd_files = list()
        for file in files:
            if file.endswith(".pyd"):
                pyd_files.append(file)
        for pyd_file in pyd_files:
            try:
                shutil.move(pyd_file,
                            to_folder)  # shutil.Error: Destination path 'D:\David\rd\pack_del\build' already exists
            except shutil.Error as e:
                err_msg = f"e: {e}"
                print(f"{err_msg}")
                if "already exists" in err_msg:
                    is_substitute = input("请问是否替换?,输入y【Y】或者n【N】:")
                    if is_substitute in ['y', 'Y']:
                        _, file_name, _, _ = split_filename(pyd_file)
                        os.remove(os.path.join(to_folder, file_name))
                        shutil.move(pyd_file, to_folder)
                    elif is_substitute in ['n', 'N']:
                        continue


def os_system(cmd_str):
    ret = os.system(cmd_str)
    print(ret)


def os_popen(cmd_str):
    f = os.popen(cmd_str, 'r')

    d = f.read()
    print(d)
    f.close()


def creat_setup_file(file, file_sname):
    # 1, 新建一个 setup.py文件(文件名可以随意命名)里面代码如下【code_name为要打包的py文件】
    with open(f"setup.py", 'w') as fw:
        fw.write(f"""
from distutils.core import setup
from Cython.Build import cythonize
    
setup(
    name="{file_sname}",
    ext_modules=cythonize(r"{file}"),
)""")


def pack_one(file, interpreter_path, to_folder):
    """将传入的一个file(py文件)打包为pyd"""

    paras = {
        "file": file,
        "interpreter_path": interpreter_path,
        "to_folder": to_folder,
    }

    pack_pyd_process(**paras)


def pack_all_in_txt(txt_file, interpreter_path, to_folder):
    """将txt里面的所有py文件打包为pyd"""

    files = [file.strip() for file in open(txt_file, 'r').readlines()]
    print(f"files: 【开始】{files}【完】")
    for file in files:
        paras = {
            "file": file,
            "interpreter_path": interpreter_path,
            "to_folder": to_folder,
        }

        pack_pyd_process(**paras)


def main():
    """pack_interface"""

    file = input("请输入要打包的py文件或者txt文件(内容为n行py文件名)的全路径文件名:")
    interpreter_path = input("请输入解释器的全路径文件名:")
    to_folder = input("请输入打包好的pyd存放目标路径:")

    if file.endswith(".py"):
        pack_one(file, interpreter_path, to_folder)
    elif file.endswith(".txt"):
        try:
            pack_all_in_txt(file, interpreter_path, to_folder)
        except Exception as e:
            print(f"e: {e}")


if __name__ == '__main__':
    main()

结果:

	"""
	请输入要打包的py文件全路径文件名:\pack_del\pack_pys.txt
    请输入解释器的全路径文件名:D:\David\venvs\venv_anctest_ws_32\Scripts
    请输入打包好的pyd存放目标路径:\pack_del
    
    
    D:\David\venvs\venv_anctest_ws_32\Scripts\pythonw.exe D:/David/rd/code/rd_test/pack_pyd/test.py
    请输入要打包的py文件【所在txt】的txt全路径文件名:\pack_del\pack_pys.txt
    请输入解释器的全路径文件名:D:\David\venvs\venv_anctest_ws_32\Scripts
    请输入打包好的pyd存放目标路径:\pack_del
    files: 【开始】['\\pack_del\\aaa.py', '\\pack_del\\asio_sd88.py']【完】
    running build_ext
    
    e: Destination path '\pack_del\build' already exists
    请问是否替换build?,输入y【Y】或者n【N】:y
    e: Destination path '\pack_del\aaa.cp36-win32.pyd' already exists
    请问是否替换?,输入y【Y】或者n【N】:y
    running build_ext
    building 'asio_sd88' extension
    creating build
    creating build\temp.win32-3.6
    creating build\temp.win32-3.6\Release
    creating build\temp.win32-3.6\Release\David
    creating build\temp.win32-3.6\Release\David\rd
    creating build\temp.win32-3.6\Release\David\rd\pack_del
    C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\BIN\cl.exe /c /nologo /Ox /W3 /GL /DNDEBUG /MD -ID:\David\venvs\venv_anctest_ws_32\include -IC:\Users\test\AppData\Local\Programs\Python\Python36-32\include -IC:\Users\test\AppData\Local\Programs\Python\Python36-32\include "-IC:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\INCLUDE" "-IC:\Program Files (x86)\Windows Kits\10\include\10.0.22621.0\ucrt" "-IC:\Program Files (x86)\Windows Kits\10\include\10.0.22621.0\shared" "-IC:\Program Files (x86)\Windows Kits\10\include\10.0.22621.0\um" "-IC:\Program Files (x86)\Windows Kits\10\include\10.0.22621.0\winrt" /Tc\pack_del\asio_sd88.c /Fobuild\temp.win32-3.6\Release\David\rd\pack_del\asio_sd88.obj
    asio_sd88.c
    C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\BIN\link.exe /nologo /INCREMENTAL:NO /LTCG /DLL /MANIFEST:EMBED,ID=2 /MANIFESTUAC:NO /LIBPATH:D:\David\venvs\venv_anctest_ws_32\libs /LIBPATH:C:\Users\test\AppData\Local\Programs\Python\Python36-32\libs /LIBPATH:C:\Users\test\AppData\Local\Programs\Python\Python36-32 /LIBPATH:D:\David\venvs\venv_anctest_ws_32\PCbuild\win32 "/LIBPATH:C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\LIB" "/LIBPATH:C:\Program Files (x86)\Windows Kits\10\lib\10.0.22621.0\ucrt\x86" "/LIBPATH:C:\Program Files (x86)\Windows Kits\10\lib\10.0.22621.0\um\x86" /EXPORT:PyInit_asio_sd88 build\temp.win32-3.6\Release\David\rd\pack_del\asio_sd88.obj /OUT:\code\rd_test\pack_pyd\asio_sd88.cp36-win32.pyd /IMPLIB:build\temp.win32-3.6\Release\David\rd\pack_del\asio_sd88.cp36-win32.lib
       Creating library build\temp.win32-3.6\Release\David\rd\pack_del\asio_sd88.cp36-win32.lib and object build\temp.win32-3.6\Release\David\rd\pack_del\asio_sd88.cp36-win32.exp
    Generating code
    Finished generating code
    
    e: Destination path '\pack_del\build' already exists
    请问是否替换build?,输入y【Y】或者n【N】:y
    e: Destination path '\pack_del\asio_sd88.cp36-win32.pyd' already exists
    请问是否替换?,输入y【Y】或者n【N】:y
    
    Process finished with exit code 0
	"""
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值