目录
一、安装包
二、打包命令
编辑
编辑
三、报错
总结
一、安装包
pip install Pyinstaller
二、打包命令
Pyinstaller -F -w 文件名.py
https://www.jb51.net/article/109195.htm
三、报错
Fatal error: PyInstaller does not include a pre-compiled bootloader for your
platform. For more details and instructions how to build the bootloader see
这个问题的具体原因我也不知道,看了很多文章都没有解决。直到这一篇:Pyinstaller缺少引导加载程序
我创建了个新的虚拟环境,下载pyinstaller源码包安装(python setup.py install) 然后在打包,就可以了。
总结
自动打包代码
# coding=utf-8
'''
@date:2023/11/24 12:58
@mail:xiaochun235@qq.com
@Content: 打包
'''
# coding=utf-8
import os
import shutil
import traceback
import platform
import subprocess
import sys
from common import *
import time
import zipfile
# 获取当前目录的上上层
BASE_PATH = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
# 当前目录
config_path = os.path.join(os.path.abspath(os.path.dirname(__file__)),'config.yaml')
if os.path.exists(config_path):
CURRENT_PATH = os.path.abspath(os.path.dirname(__file__))
else:
CURRENT_PATH = BASE_PATH
print("CURRENT_PATH:", CURRENT_PATH)
PROJECT_NAME="selenium自动化执行"
# 删除文件内容
delete_files = ["build", "dist", "bin.spec",f'{PROJECT_NAME}']
PYTHON_VENV_PATH = 'D:/pthon_venv/selenium_project_venv/Lib/site-packages'
# 需要复制的文件及其 文件夹名
copy_file_name_list=['config.yaml','chrome_win32',f'dist/{PROJECT_NAME}/{PROJECT_NAME}.exe',f'dist/{PROJECT_NAME}/{PROJECT_NAME}.bat',f'dist/{PROJECT_NAME}/_internal']
# 打包的 python 文件
pack_python_file_name='main.py'
# 打包文件名
shijian=time.strftime("%Y-%m-%d%H%M%S", time.localtime())
GET_CURRENT_FILES = CURRENT_PATH
# 目标目标文件
TARGET=os.path.join(CURRENT_PATH,PROJECT_NAME) #目标目录
# cmd 运行命令
def run_pack(instructions):
system_return = os.system(instructions)
print(system_return)
return system_return
# 删除原来报道好的文件
def delete_file(delete_files):
print("获取当前文件夹路径:", GET_CURRENT_FILES)
files = os.listdir(GET_CURRENT_FILES)
print("当前文件目录下的所有文件及其文件夹名称", files)
print("需要删除的文件为", delete_files)
# 循环删除文件
for x in files:
if x in delete_files:
file_path = os.path.join(GET_CURRENT_FILES, x)
try:
if os.path.isdir(file_path): # 判断是否是文件夹
# 删除不支持删除文件 只能删除文件夹
try:
shutil.rmtree(file_path)
except Exception as e:
logger.error(f"删除文件报错{file_path}")
else:
# # 删除单个文件夹
os.remove(os.path.join(GET_CURRENT_FILES, x))
except Exception as e:
print("文件不存在")
print(traceback.format_exc())
finally:
pass
# 创建文件 dat
def create_a_file(file_path, file_content):
t = open(file_path, mode='w')
t.write(file_content)
# 判断 PiP包是否存在
def is_existence_package(instructions):
read_cmd = os.popen(f"pip show {instructions}").read()
read_cmd_list = read_cmd.split("\n")
arr_list = []
for x in read_cmd_list:
list_kv = x.split(": ")
arr_list += list_kv
keys = []
vlu = []
for x in range(0, len(arr_list)):
if x % 2 == 0:
keys.append(arr_list[x])
else:
vlu.append(arr_list[x])
kv = zip(keys, vlu)
version_dict = dict(kv)
if version_dict.get("Version"):
return True
else:
return False
# 打开文件夹
def open_fp(fp: str):
"""
打开文件或文件夹
优点: 代码输入参数少, 复制粘贴即可使用, 支持在mac和win上使用, 打开速度快稳定;
:param fp: 需要打开的文件或文件夹路径
"""
systemType: str = platform.platform() # 获取系统类型
if 'mac' in systemType: # 判断以下当前系统类型
fp: str = fp.replace("\\", "/") # mac系统下,遇到`\\`让路径打不开,不清楚为什么哈,觉得没必要的话自己可以删掉啦,18行那条也是
subprocess.call(["open", fp])
else:
fp: str = fp.replace("/", "\\") # win系统下,有时`/`让路径打不开
os.startfile(fp)
# 初始化
def init_program():
# 删除文件
delete_file(delete_files)
# 安装包
if not is_existence_package("Pyinstaller"):
run_pack("pip install Pyinstaller")
# 打包需要额外打包的内容 虚拟环境pip 包
xu_ni_huanjing = PYTHON_VENV_PATH
# 打包后的名称
sheng_cheng_name = PROJECT_NAME
# 打包图标
ico = "favicon.ico"
'''
-F 生成结果是一个 exe 文件,所有的第三方依赖、资源和diamante均被打包进该 exe 内
-D 生成结果是一个目录,各种第三方依赖、资源和exe 同时存储在该目录(默认)
-a 不包含 unicode 支持
-d 执行的 exe 时间 ,会输出一些 log ,有助于查错
-w 不显示命令行窗口
-c 显示命令行窗口 (默认)
-p 指定额外的 import 路径,类似于使用 python path
-i 指定图标
-v 显示版本号
-n 生成 .exe 的文件名
'''
# instructions = f"Pyinstaller -p {xu_ni_huanjing} -i {ico} {pack_python_file_name} -n {sheng_cheng_name} -w"
instructions = f"Pyinstaller -p {xu_ni_huanjing} -i {ico} {pack_python_file_name} -n {sheng_cheng_name}"
i = run_pack(instructions)
# 创建bat文件
if i == 0:
file_content = f".\\{sheng_cheng_name}.exe"
file_path = f"dist/{sheng_cheng_name}/{sheng_cheng_name}.bat"
create_a_file(file_path, file_content)
# 复制模板到指定的位置
fuXhiWengJian(copy_file_name_list, TARGET)
# 重命名文件夹名称
parent_path = os.path.dirname(TARGET)
old_folder_name = TARGET #文件夹名称'
new_folder_name = os.path.join(parent_path,PROJECT_NAME)#'新文件夹名称'
os.rename(old_folder_name, new_folder_name)
# 将文件打包为zip
logger.info(f"正在为你压缩{new_folder_name}")
zip_folder(new_folder_name,os.path.join(os.path.dirname(new_folder_name),f'{PROJECT_NAME}{shijian}.zip'))
logger.info(f"压缩完成{os.path.join(os.path.dirname(new_folder_name),f'{PROJECT_NAME}{shijian}.zip')}")
## 打开文件夹路径
open_fp(new_folder_name)
delete_file(["build", "dist", "bin.spec"])
# 复制到目标文件
# shutil.copy() 复制文件
def fuXhiWengJian(copy_file_name_list, target):
'''
:param source: 需要复制的文件及文件目录
:param target: 复制到我目标位置
:return:
'''
# 循环复制
if not os.path.exists(target):
os.makedirs(target) # 创建路径 创建多层目录
for name in copy_file_name_list:
source = os.path.join(CURRENT_PATH,name)
if os.path.isdir(source):
try:
last_dir = os.path.split(source)[-1]
shutil.copytree(source, os.path.join(target,last_dir))
except FileExistsError as e:
logger.error(msg=f"复制文件报错:{e}")
else:
shutil.copy2(source, target)
# 将文件夹压缩
def zip_folder(folder_path, output_path):
'''
:param folder_path: 要压缩的文件夹路径
:param output_path: 输出的zip文件路径
:return:
'''
with zipfile.ZipFile(output_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
for root, dirs, files in os.walk(folder_path):
for file in files:
zipf.write(os.path.join(root, file), os.path.relpath(os.path.join(root, file), folder_path))
if __name__ == "__main__":
init_program()