提交 6f3c707e authored 作者: 陈泽健's avatar 陈泽健

feat(预定系统): 更新脚本支持多环境配置

- 新增 JSON 配置文件,支持不同环境的配置
- 重构代码,实现环境配置的动态加载- 添加命令行参数,允许选择更新环境
- 优化日志输出,提高错误处理能力
上级 8865cfb8
......@@ -13,6 +13,7 @@
- pip install python-docx
- pip install tqdm
- pip install paramiko tqdm
- pip install pyinstaller
- 若切换电脑环境后需要输入指令: 将本地库导入到外部库中。
- # 找到 site-packages 路径
......
import os
from datetime import datetime
def get_latest_folder(path):
"""获取指定路径下的最新文件夹(带调试信息)"""
print(f"\n[DEBUG] 开始查找最新文件夹,路径: {path}")
# 确保路径存在
if not os.path.exists(path):
print(f"[ERROR] 路径不存在: {path}")
raise FileNotFoundError(f"指定路径不存在: {path}")
print("[DEBUG] 路径验证通过")
# 获取所有文件夹
try:
all_items = os.listdir(path)
folders = [f for f in all_items if os.path.isdir(os.path.join(path, f))]
print(f"[DEBUG] 找到 {len(folders)} 个文件夹: {folders}")
except Exception as e:
print(f"[ERROR] 读取目录失败: {str(e)}")
raise
# 如果没有文件夹,返回None
if not folders:
print("[WARNING] 未找到任何文件夹")
return None
# 获取每个文件夹的修改时间
folder_times = []
for f in folders:
try:
full_path = os.path.join(path, f)
mtime = os.path.getmtime(full_path)
folder_times.append((f, mtime))
print(f"[DEBUG] 文件夹: {f}, 修改时间: {datetime.fromtimestamp(mtime)}")
except Exception as e:
print(f"[WARNING] 无法获取 {f} 的时间信息: {str(e)}")
continue
# 按修改时间排序,找到最新的文件夹
if not folder_times:
print("[ERROR] 没有可用的文件夹时间信息")
return None
latest_folder = max(folder_times, key=lambda x: x[1])[0]
result = os.path.join(path, latest_folder)
print(f"[DEBUG] 确定最新文件夹: {result}")
return result
def get_latest_jar_from_folder(folder_path):
"""从指定文件夹中获取最新的JAR包(带调试信息)"""
print(f"\n[DEBUG] 开始查找JAR包,路径: {folder_path}")
# 获取文件夹中的所有文件
try:
files = [f for f in os.listdir(folder_path) if f.endswith('.jar')]
print(f"[DEBUG] 找到 {len(files)} 个JAR文件: {files}")
except Exception as e:
print(f"[ERROR] 读取JAR文件失败: {str(e)}")
return None
# 如果没有JAR包,返回None
if not files:
print("[WARNING] 未找到任何JAR文件")
return None
# 获取每个JAR包的修改时间
jar_times = []
for f in files:
try:
full_path = os.path.join(folder_path, f)
mtime = os.path.getmtime(full_path)
jar_times.append((f, mtime))
print(f"[DEBUG] JAR文件: {f}, 修改时间: {datetime.fromtimestamp(mtime)}")
except Exception as e:
print(f"[WARNING] 无法获取 {f} 的时间信息: {str(e)}")
continue
# 按修改时间排序,找到最新的JAR包
if not jar_times:
print("[ERROR] 没有可用的JAR文件时间信息")
return None
latest_jar = max(jar_times, key=lambda x: x[1])[0]
result = os.path.join(folder_path, latest_jar)
print(f"[DEBUG] 确定最新JAR文件: {result}")
return result
def get_frontend_files_from_folder(folder_path, files_to_update):
"""从指定文件夹中获取前端文件(带调试信息)"""
print(f"\n[DEBUG] 开始查找前端文件,路径: {folder_path}")
print(f"[DEBUG] 需要查找的文件模式: {files_to_update}")
frontend_files = {}
for item in files_to_update:
try:
if item.endswith('/'):
dir_name = item[:-1]
dir_path = os.path.join(folder_path, dir_name)
if os.path.exists(dir_path):
files = [os.path.join(dir_name, f) for f in os.listdir(dir_path)]
frontend_files[dir_name] = files
print(f"[DEBUG] 找到目录 {dir_name}, 包含 {len(files)} 个文件")
else:
frontend_files[dir_name] = []
print(f"[WARNING] 目录不存在: {dir_path}")
elif item == '*.worker.js':
worker_files = [f for f in os.listdir(folder_path) if f.endswith('.worker.js')]
frontend_files['worker.js'] = worker_files
print(f"[DEBUG] 找到 {len(worker_files)} 个worker文件: {worker_files}")
else:
file_path = os.path.join(folder_path, item)
if os.path.exists(file_path):
frontend_files[item] = item
print(f"[DEBUG] 找到文件: {item}")
else:
frontend_files[item] = None
print(f"[WARNING] 文件不存在: {item}")
except Exception as e:
print(f"[ERROR] 处理 {item} 时出错: {str(e)}")
frontend_files[item] = None
print(f"[DEBUG] 最终获取的文件清单: {frontend_files}")
return frontend_files
def main():
"""主测试函数"""
print("=" * 50 + "\n开始测试\n" + "=" * 50)
# 测试路径配置
test_paths = {
"backend": r"\\192.168.9.9\deploy\01会议预定\标准版本-长期运维\01版本管理\01后端运行服务\内部预定",
"frontend": r"\\192.168.9.9\deploy\00项目管理\2025\L 兰州中石化项目\01版本管理\02前端PC网页",
"local_test": os.path.join(os.path.dirname(__file__), "test_data") # 本地测试路径
}
# 路径连通性测试
print("\n[TEST] 正在验证路径连通性...")
for name, path in test_paths.items():
print(f"{name}路径: {path} {'可用' if os.path.exists(path) else '不可用'}")
# 正式测试
test_cases = [
("后端服务测试", test_paths["backend"], ['*.jar']),
("前端服务测试", test_paths["frontend"], ['*.worker.js', 'index.html', 'static/']),
("本地测试", test_paths["local_test"], ['test.txt', 'subdir/'])
]
for name, path, patterns in test_cases:
print(f"\n{'=' * 20} {name} {'=' * 20}")
print(f"测试路径: {path}")
latest_folder = get_latest_folder(path)
if not latest_folder:
print(f"[RESULT] {name} - 未找到有效文件夹")
continue
print(f"[RESULT] 最新文件夹: {latest_folder}")
# 根据模式执行不同测试
if '*.jar' in patterns:
jar_file = get_latest_jar_from_folder(latest_folder)
print(f"[RESULT] 最新JAR文件: {jar_file if jar_file else '未找到'}")
else:
files = get_frontend_files_from_folder(latest_folder, patterns)
print(f"[RESULT] 找到的文件: {files}")
if __name__ == "__main__":
main()
print("\n测试完成,请检查上方调试信息")
......@@ -326,4 +326,6 @@
96. 2025-06-18:
- base增加read_xlsx_data_auto函数,支持sheet_name为None时,默认遍历整个测试用例所有模块从第一个sheet到最后的sheet执行,若sheet_name传参时,则为单独执行某个模块测试。
- 删除原函数,避免混淆。
- read_xlsx_data函数优化,调试兰州中石化项目自动化测试。1
\ No newline at end of file
- read_xlsx_data函数优化,调试兰州中石化项目自动化测试。
97. 2025-07-01:
- feat(预定系统): 更新脚本支持多环境配置,新增 JSON 配置文件,支持不同环境的配置,重构代码,实现环境配置的动态加载- 添加命令行参数,允许选择更新环境,优化日志输出,提高错误处理能力。
\ No newline at end of file
{
"LZSH_Test": {
"ssh": {
"host": "139.159.163.86",
"port": 22,
"user": "root",
"password": "hzpassw0RD@KP"
},
"version_discovery": {
"backend": {
"inner": {
"search_path": "\\\\192.168.9.9\\deploy\\01会议预定\\标准版本-长期运维\\01版本管理\\01后端运行服务\\内部预定",
"file_pattern": "*.jar"
},
"external": {
"search_path": "\\\\192.168.9.9\\deploy\\01会议预定\\标准版本-长期运维\\01版本管理\\01后端运行服务\\对外预定",
"file_pattern": "*.jar"
}
},
"frontend": {
"front": {
"search_path": "\\\\192.168.9.9\\deploy\\00项目管理\\2025\\L 兰州中石化项目\\01版本管理\\02前端PC网页",
"files_to_update": ["*.worker.js", "index.html", "static/"]
},
"admin": {
"search_path": "\\\\192.168.9.9\\deploy\\01会议预定\\标准版本-预定后台\\01版本管理",
"files_to_update": ["index.html", "static/"]
}
}
},
"deploy_config": {
"front": {
"remote_dir": "/var/www/java/ubains-web-2.0/",
"backup_dir": "/var/www/java/ubains-web-2.0/backup/",
"type": "frontend"
},
"admin": {
"remote_dir": "/var/www/java/ubains-web-admin/",
"backup_dir": "/var/www/java/ubains-web-admin/backup/",
"type": "frontend"
},
"inner": {
"remote_dir": "/var/www/java/api-java-meeting2.0/",
"backup_dir": "/var/www/java/api-java-meeting2.0/backup/",
"jar_name": "ubains-meeting-inner-api-1.0-SNAPSHOT.jar",
"container": "ujava2",
"exec_cmd": "/var/www/java/api-java-meeting2.0/run.sh",
"type": "backend"
},
"external": {
"remote_dir": "/var/www/java/external-meeting-api/",
"backup_dir": "/var/www/java/external-meeting-api/backup/",
"jar_name": "ubains-meeting-api-1.0-SNAPSHOT.jar",
"container": "ujava2",
"exec_cmd": "/var/www/java/external-meeting-api/run.sh",
"type": "backend"
}
}
},
"Test_235": {
"ssh": {
"host": "192.168.5.235",
"port": 22,
"user": "root",
"password": "Ubains@123"
},
"version_discovery": {
"backend": {
"inner": {
"search_path": "\\\\192.168.9.9\\deploy\\01会议预定\\标准版本-长期运维\\01版本管理\\01后端运行服务\\内部预定",
"file_pattern": "*.jar"
},
"external": {
"search_path": "\\\\192.168.9.9\\deploy\\01会议预定\\标准版本-长期运维\\01版本管理\\01后端运行服务\\对外预定",
"file_pattern": "*.jar"
}
},
"frontend": {
"front": {
"search_path": "\\\\192.168.9.9\\deploy\\01会议预定\\标准版本-长期运维\\01版本管理\\02前端PC网页\\标准版本-长期运维\\2025年度",
"files_to_update": ["*.worker.js", "index.html", "static/"]
},
"admin": {
"search_path": "\\\\192.168.9.9\\deploy\\01会议预定\\标准版本-预定后台\\01版本管理",
"files_to_update": ["index.html", "static/"]
}
}
},
"deploy_config": {
"front": {
"remote_dir": "/var/www/java/ubains-web-2.0/",
"backup_dir": "/var/www/java/ubains-web-2.0/backup/",
"type": "frontend"
},
"admin": {
"remote_dir": "/var/www/java/ubains-web-admin/",
"backup_dir": "/var/www/java/ubains-web-admin/backup/",
"type": "frontend"
},
"inner": {
"remote_dir": "/var/www/java/api-java-meeting2.0/",
"backup_dir": "/var/www/java/api-java-meeting2.0/backup/",
"jar_name": "ubains-meeting-inner-api-1.0-SNAPSHOT.jar",
"container": "ujava2",
"exec_cmd": "/var/www/java/api-java-meeting2.0/run.sh",
"type": "backend"
},
"external": {
"remote_dir": "/var/www/java/external-meeting-api/",
"backup_dir": "/var/www/java/external-meeting-api/backup/",
"jar_name": "ubains-meeting-api-1.0-SNAPSHOT.jar",
"container": "ujava2",
"exec_cmd": "/var/www/java/external-meeting-api/run.sh",
"type": "backend"
}
}
}
}
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
预定系统全栈更新脚本 - 最终稳定
预定系统全栈更新脚本 - 支持多环境配置
功能:
1. 从本地共享路径自动发现最新版本
2. 先备份再更新服务器上的前后端服务
......@@ -11,6 +11,8 @@
import os
import sys
import json
import argparse
import re
import fnmatch
from datetime import datetime
......@@ -22,87 +24,26 @@ import paramiko
from tqdm import tqdm
class Config:
"""系统配置类"""
# ===== 连接配置 =====
SSH_PORT = 22
SSH_USER = "root"
SSH_PASSWORD = os.getenv('DEPLOY_SSH_PASSWORD') or "hzpassw0RD@KP"
# ===== 服务器配置 =====
SERVER_HOST = '139.159.163.86' # 默认使用兰州中石化测试环境
# 版本发现配置(本地网络路径)
VERSION_DISCOVERY = {
'backend': {
'inner': {
'search_path': r"\\192.168.9.9\deploy\01会议预定\标准版本-长期运维\01版本管理\01后端运行服务\内部预定",
'file_pattern': '*.jar'
},
'external': {
'search_path': r"\\192.168.9.9\deploy\01会议预定\标准版本-长期运维\01版本管理\01后端运行服务\对外预定",
'file_pattern': '*.jar'
}
},
'frontend': {
'front': {
'search_path': r"\\192.168.9.9\deploy\00项目管理\2025\L 兰州中石化项目\01版本管理\02前端PC网页",
'files_to_update': ['*.worker.js', 'index.html', 'static/']
},
'admin': {
'search_path': r"\\192.168.9.9\deploy\01会议预定\标准版本-预定后台\01版本管理",
'files_to_update': ['index.html', 'static/']
}
}
}
# ===== 部署目标 & 备份配置(远程)=====
DEPLOY_CONFIG = {
'front': {
'remote_dir': "/var/www/java/ubains-web-2.0/",
'backup_dir': "/var/www/java/ubains-web-2.0/backup/",
'type': 'frontend'
},
'admin': {
'remote_dir': "/var/www/java/ubains-web-admin/",
'backup_dir': "/var/www/java/ubains-web-admin/backup/",
'type': 'frontend'
},
'inner': {
'remote_dir': "/var/www/java/api-java-meeting2.0/",
'backup_dir': "/var/www/java/api-java-meeting2.0/backup/",
'jar_name': "ubains-meeting-inner-api-1.0-SNAPSHOT.jar",
'container': "ujava2",
'exec_cmd': "/var/www/java/api-java-meeting2.0/run.sh", # 绝对路径
'type': 'backend'
},
'external': {
'remote_dir': "/var/www/java/external-meeting-api/",
'backup_dir': "/var/www/java/external-meeting-api/backup/",
'jar_name': "ubains-meeting-api-1.0-SNAPSHOT.jar",
'container': "ujava2",
'exec_cmd': "/var/www/java/external-meeting-api/run.sh",
'type': 'backend'
}
}
# 日志过滤规则
IGNORABLE_LOG_PATTERNS = [
re.compile(r'unexpected operator'),
re.compile(r'Usage: kill'),
re.compile(r'kill -l'),
re.compile(r'Java HotSpot\(TM\)'),
re.compile(r'SLF4J:'),
re.compile(r'Listening for transport'),
re.compile(r'Starting Application'),
re.compile(r'tail:.*file truncated'),
re.compile(r'log4j:WARN')
]
def load_config(env="test"):
"""
加载 JSON 配置文件中的环境配置
"""
config_path = os.path.join(os.path.dirname(__file__), "Server_Config.json")
if not os.path.exists(config_path):
raise FileNotFoundError(f"找不到配置文件: {config_path}")
with open(config_path, "r", encoding="utf-8") as f:
full_config = json.load(f)
if env not in full_config:
raise ValueError(f"配置中没有找到环境 '{env}'")
return full_config[env]
class Deployer:
def __init__(self):
def __init__(self, env_config):
self.env_config = env_config
self.ssh = paramiko.SSHClient()
self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
self.sftp = None
......@@ -121,15 +62,16 @@ class Deployer:
return log
def connect(self):
ssh_config = self.env_config['ssh']
max_retries = 3
for attempt in range(1, max_retries + 1):
try:
self.logger(f"尝试连接服务器 ({attempt}/{max_retries})...", important=True)
self.ssh.connect(
hostname=Config.SERVER_HOST,
port=Config.SSH_PORT,
username=Config.SSH_USER,
password=Config.SSH_PASSWORD,
hostname=ssh_config['host'],
port=ssh_config['port'],
username=ssh_config['user'],
password=ssh_config['password'],
timeout=30,
banner_timeout=200
)
......@@ -176,7 +118,7 @@ class Deployer:
return ""
def _discover_backend_version(self, service_type):
backend_config = Config.VERSION_DISCOVERY.get('backend')
backend_config = self.env_config.get('version_discovery', {}).get('backend')
if not backend_config:
self.logger("版本发现配置中缺少 'backend'", "ERROR")
return None
......@@ -196,7 +138,7 @@ class Deployer:
# 提取本地版本号
local_version = self.extract_backend_version(os.path.basename(latest_folder))
# 获取远程 JAR 文件版本号(假设 JAR 文件名包含版本号)
# 获取远程 JAR 文件路径
remote_jar_path = os.path.join(config['search_path'], config['file_pattern'].replace("*.", ""))
if self._remote_file_exists(remote_jar_path):
remote_jar_name = os.path.basename(remote_jar_path)
......@@ -216,7 +158,7 @@ class Deployer:
return {'local_jar': jar_file, 'local_version': local_version}
def _discover_frontend_version(self, frontend_type):
frontend_config = Config.VERSION_DISCOVERY.get('frontend')
frontend_config = self.env_config.get('version_discovery', {}).get('frontend')
if not frontend_config:
self.logger("版本发现配置中缺少 'frontend'", "ERROR")
return None
......@@ -237,7 +179,12 @@ class Deployer:
local_version = self.extract_frontend_version(os.path.basename(latest_folder))
# 获取远程版本号(假设有一个 version.txt 文件记录版本号)
remote_version_path = os.path.join(Config.DEPLOY_CONFIG[frontend_type]['remote_dir'], 'version.txt')
deploy_config = self.env_config.get('deploy_config', {}).get(frontend_type)
if not deploy_config:
self.logger(f"找不到前端 {frontend_type} 的更新配置", "ERROR")
return None
remote_version_path = os.path.join(deploy_config['remote_dir'], 'version.txt')
if self._remote_file_exists(remote_version_path):
remote_version_str = self._read_remote_file(remote_version_path)
remote_version = tuple(map(int, remote_version_str.strip().split('.')))
......@@ -249,7 +196,23 @@ class Deployer:
return {'local_dir': latest_folder, 'files': config['files_to_update'], 'local_version': local_version}
def extract_backend_version(self, folder_name):
match = re.search(r'V(\d+\.\d+\.\d+\.\d+)', folder_name)
if match:
return tuple(map(int, match.group(1).split('.')))
return (0, 0, 0, 0)
def extract_frontend_version(self, folder_name):
match = re.search(r'(\d+\.\d+\.\d+\.\d+)', folder_name)
if match:
return tuple(map(int, match.group(1).split('.')))
return (0, 0, 0, 0)
def _execute_command(self, command):
ignorable_patterns = self.env_config.get("ignorable_log_patterns", [])
if ignorable_patterns:
ignorable_patterns = [re.compile(p) for p in ignorable_patterns]
try:
stdin, stdout, stderr = self.ssh.exec_command(command)
exit_code = stdout.channel.recv_exit_status()
......@@ -260,7 +223,7 @@ class Deployer:
self.logger(f"命令输出: {output}", "INFO")
if error and exit_code != 0:
for line in error.splitlines():
if any(p.search(line) for p in Config.IGNORABLE_LOG_PATTERNS):
if any(p.search(line) for p in ignorable_patterns):
continue
self.logger(f"命令错误: {line}", "ERROR")
return False
......@@ -269,18 +232,6 @@ class Deployer:
self.logger(f"命令执行失败: {e}", "ERROR")
return False
def extract_backend_version(self, folder_name):
match = re.search(r'V(\d+\.\d+\.\d+\.\d+)', folder_name)
if match:
return tuple(map(int, match.group(1).split('.')))
return (0, 0, 0, 0)
def extract_frontend_version(self, folder_name):
match = re.search(r'(\d+\.\d+\.\d+\.\d+)', folder_name)
if match:
return tuple(map(int, match.group(1).split('.')))
return (0, 0, 0, 0)
def _upload_jar(self, local_jar, remote_dir, jar_name):
try:
remote_path = os.path.join(remote_dir, jar_name)
......@@ -311,7 +262,8 @@ class Deployer:
return False
def _backup_and_update_backend(self, service_type, version_info):
config = Config.DEPLOY_CONFIG.get(service_type)
deploy_config = self.env_config.get('deploy_config', {})
config = deploy_config.get(service_type)
if not config:
self.logger(f"找不到名为 {service_type} 的部署配置", "ERROR")
return False
......@@ -408,7 +360,7 @@ class Deployer:
def _write_remote_file(self, remote_path, content):
try:
with self.sftp.open(remote_path, 'w') as fp:
fp.write(content)
fp.write(content.encode('utf-8'))
return True
except Exception as e:
self.logger(f"写入远程文件失败: {e}", "ERROR")
......@@ -425,7 +377,7 @@ class Deployer:
# 获取本地文件大小用于进度条
file_size = os.path.getsize(tmp_archive)
remote_archive = "/tmp/" + os.path.basename(tmp_archive) # 强制使用 Linux 风格路径
remote_archive = "/tmp/" + os.path.basename(tmp_archive)
self.logger(f"正在上传文件到远程服务器: {remote_archive}")
......@@ -433,7 +385,7 @@ class Deployer:
progress_bar = tqdm(total=file_size, unit='B', unit_scale=True, desc="上传进度")
def upload_progress_callback(sent, total):
progress_bar.update(sent - progress_bar.n) # 更新进度条
progress_bar.update(sent - progress_bar.n)
# 使用带有进度条的上传
self.sftp.put(tmp_archive, remote_archive, callback=upload_progress_callback)
......@@ -448,7 +400,8 @@ class Deployer:
return False
def _update_frontend(self, frontend_type):
config = Config.DEPLOY_CONFIG.get(frontend_type)
deploy_config = self.env_config.get('deploy_config', {})
config = deploy_config.get(frontend_type)
if not config:
self.logger(f"找不到名为 {frontend_type} 的前端部署配置", "ERROR")
return False
......@@ -522,15 +475,28 @@ class Deployer:
if __name__ == "__main__":
print("\n=== 预定系统服务更新工具 ===")
if Config.SSH_PASSWORD == "hzpassw0RD@KP":
parser = argparse.ArgumentParser(description="预定系统更新工具")
parser.add_argument("--env", choices=["LZSH_Test", "Test_235"], default="LZSH_Test",
help="选择更新环境 (LZSH_Test/Test_235)")
args = parser.parse_args()
try:
env_config = load_config(args.env)
except Exception as e:
print(f"\033[1;31m❌ 配置加载失败: {e}\033[0m")
sys.exit(1)
print(f"\n=== 预定系统服务更新工具 [{args.env.upper()} 环境] ===")
ssh_config = env_config['ssh']
if ssh_config['password'] in ("hzpassw0RD@KP", "prod_default_pass"):
print("\033[1;31m! 安全警告: 您正在使用默认密码!\033[0m")
deployer = Deployer()
deployer = Deployer(env_config)
success = deployer.deploy()
if success:
print("\n\033[1;32m✅ 全栈更新成功!\033[0m")
sys.exit(0)
else:
print("\n\033[1;31m❌ 更新失败,请检查日志。\033[0m")
sys.exit(1)
\ No newline at end of file
sys.exit(1)
......@@ -73,11 +73,16 @@ start_workers(3)
# 更新兰州项目环境,并定时执行兰州中石化项目测试任务
# 添加定时任务
schedule.every().day.at("09:05").do(
schedule.every().day.at("18:28").do(
run_task,
pull_remote_devlop.Deployer().deploy
)
schedule.every().day.at("09:10").do(run_task, run_automation_test, report_title="兰州中石化项目测试报告", report_url_prefix="http://nat.ubainsyun.com:31135", test_case="兰州中石化项目", ding_type="标准版巡检")
schedule.every().day.at("19:00").do(
run_task,
pull_remote_devlop.Deployer().deploy
)
schedule.every().day.at("19:15").do(run_task, run_automation_test, report_title="兰州中石化项目测试报告", report_url_prefix="http://nat.ubainsyun.com:31135", test_case="兰州中石化项目", ding_type="标准版巡检")
# 定时执行展厅巡检任务
# schedule.every().day.at("07:45").do(run_task, run_automation_test, report_title="展厅巡检测试报告", report_url_prefix="http://nat.ubainsyun.com:31136", test_case="展厅巡检", ding_type="展厅巡检")
......
# 打包程序.spec
# 用于将定时执行功能测试.py 及其依赖资源打包为一个独立的 .exe 可执行文件
block_cipher = None
# ========== 分析阶段 ==========
# 指定主程序入口、搜索路径、数据目录、隐藏导入等
a = Analysis(
['定时执行功能测试.py'], # 主程序入口文件
pathex=['.'], # 当前目录作为模块搜索路径
binaries=[], # 无需额外二进制文件
datas=[
('Base', 'Base'), # Base 目录(存放基础类)
('测试数据', '测试数据'), # 测试数据目录(如 JSON、Excel 文件)
('log', 'log'), # 日志输出目录
('reports', 'reports'), # 报告生成目录
],
hiddenimports=[
'Base.base', # 显式导入 Base.base 模块
'pull_remote_devlop' # 显式导入 pull_remote_devlop 模块(防止找不到)
],
hookspath=[],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
)
# ========== 打印调试信息 ==========
# 在打包时输出被分析到的模块和资源路径,方便排查问题
import logging
logging.basicConfig(level=logging.INFO, format='%(message)s')
print("=== 被 PyInstaller 打包的模块和文件列表 ===")
# 输出隐藏导入的模块
logging.info("【Hidden Imports】:")
for mod in a.hiddenimports:
logging.info(f" - {mod}")
# 输出所有被分析到的 Python 模块路径
logging.info("\n【Python Modules Path】:")
for py_mod in a.pure:
# py_mod 是一个三元组: (modname, relpath, abspath)
logging.info(f" - {py_mod[0]} -> {py_mod[2]}")
# 输出所有复制的数据文件(如 Base/ 等)
logging.info("\n【Data Files (datas)】:")
for src, dest, datatype in a.datas:
logging.info(f" - {src} --> {dest} ({datatype})")
# 输出搜索路径(pathex)
logging.info("\n【Search Paths (pathex)】:")
for p in a.pathex:
logging.info(f" - {p}")
# ========== 构建阶段 ==========
# 创建 PYZ(纯 Python 模块归档)和 EXE(可执行文件)
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
exe = EXE(
pyz,
a.scripts,
[],
exclude_binaries=True,
name='定时执行功能测试',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
console=True, # 启用控制台输出(便于查看日志)
icon=None,
)
coll = COLLECT(
exe,
a.binaries,
a.zipfiles,
a.datas,
strip=False,
upx=True,
upx_exclude=[],
name='定时执行功能测试'
)
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论