需求:
经常要打包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
"""