fix: 修复打包后exe程序在无控制台模式下运行时的uvicorn日志配置错误
通过检测sys.frozen判断运行环境,只在打包后的exe程序中禁用日志配置, 避免AttributeError: 'NoneType' object has no attribute 'isatty'错误。 普通Python运行环境保留完整日志功能,方便调试。
This commit is contained in:
77
main.py
77
main.py
@@ -199,7 +199,39 @@ def load_data_from_excel(file_path):
|
||||
if cable_specs:
|
||||
print(f"成功加载: {len(cable_specs)} 种电缆规格")
|
||||
|
||||
return turbines, substation, cable_specs
|
||||
# 读取参数数据 (如果存在)
|
||||
system_params = {}
|
||||
param_sheet_name = None
|
||||
if 'Parameters' in xl.sheet_names:
|
||||
param_sheet_name = 'Parameters'
|
||||
elif '参数' in xl.sheet_names:
|
||||
param_sheet_name = '参数'
|
||||
|
||||
if param_sheet_name:
|
||||
try:
|
||||
params_df = pd.read_excel(xl, param_sheet_name)
|
||||
# 假设格式为两列:Parameter (参数名), Value (值)
|
||||
if len(params_df.columns) >= 2:
|
||||
for _, row in params_df.iterrows():
|
||||
key = str(row[0]).strip().lower()
|
||||
try:
|
||||
val = float(row[1])
|
||||
if 'voltage' in key or '电压' in key:
|
||||
# 检测是否为kV单位
|
||||
if 'kv' in key:
|
||||
system_params['voltage'] = val * 1000
|
||||
else:
|
||||
system_params['voltage'] = val
|
||||
elif 'factor' in key or '功率因数' in key:
|
||||
system_params['power_factor'] = val
|
||||
except ValueError:
|
||||
pass
|
||||
if system_params:
|
||||
print(f"成功加载系统参数: {system_params}")
|
||||
except Exception as e:
|
||||
print(f"读取参数Sheet失败: {e}")
|
||||
|
||||
return turbines, substation, cable_specs, system_params
|
||||
|
||||
except Exception as e:
|
||||
print(f"读取Excel文件失败: {str(e)}")
|
||||
@@ -315,7 +347,7 @@ def design_with_kmeans(turbines, substation, n_clusters=3):
|
||||
return cluster_connections + substation_connections, turbines
|
||||
|
||||
# 3.5 带容量约束的扇区扫描算法 (Capacitated Sweep) - 基础版
|
||||
def design_with_capacitated_sweep(turbines, substation, cable_specs=None):
|
||||
def design_with_capacitated_sweep(turbines, substation, cable_specs=None, voltage=VOLTAGE_LEVEL, power_factor=POWER_FACTOR):
|
||||
"""
|
||||
使用带容量约束的扇区扫描算法设计集电线路 (基础版:单次扫描)
|
||||
原理:
|
||||
@@ -325,10 +357,9 @@ def design_with_capacitated_sweep(turbines, substation, cable_specs=None):
|
||||
4. 满载后开启新回路。
|
||||
"""
|
||||
# 1. 获取电缆最大容量
|
||||
max_mw = get_max_cable_capacity_mw(cable_specs)
|
||||
|
||||
substation_coord = substation[0]
|
||||
max_mw = get_max_cable_capacity_mw(cable_specs, voltage=voltage, power_factor=power_factor)
|
||||
|
||||
substation_coord = substation[0]
|
||||
# 2. 计算角度 (使用 arctan2 返回 -pi 到 pi)
|
||||
work_df = turbines.copy()
|
||||
dx = work_df['x'] - substation_coord[0]
|
||||
@@ -417,7 +448,7 @@ def design_with_capacitated_sweep(turbines, substation, cable_specs=None):
|
||||
return cluster_connections + substation_connections, turbines
|
||||
|
||||
# 3.6 旋转扫描算法 (Rotational Sweep) - 优化版
|
||||
def design_with_rotational_sweep(turbines, substation, cable_specs=None):
|
||||
def design_with_rotational_sweep(turbines, substation, cable_specs=None, voltage=VOLTAGE_LEVEL, power_factor=POWER_FACTOR):
|
||||
"""
|
||||
使用带容量约束的扇区扫描算法设计集电线路 (优化版:旋转扫描)
|
||||
原理:
|
||||
@@ -427,7 +458,7 @@ def design_with_rotational_sweep(turbines, substation, cable_specs=None):
|
||||
4. 对每种分组方案计算MST成本,选出总成本最低的方案。
|
||||
"""
|
||||
# 1. 获取电缆最大容量
|
||||
max_mw = get_max_cable_capacity_mw(cable_specs)
|
||||
max_mw = get_max_cable_capacity_mw(cable_specs, voltage=voltage, power_factor=power_factor)
|
||||
|
||||
substation_coord = substation[0]
|
||||
|
||||
@@ -541,7 +572,7 @@ def design_with_rotational_sweep(turbines, substation, cable_specs=None):
|
||||
|
||||
return final_connections, turbines
|
||||
|
||||
def get_max_cable_capacity_mw(cable_specs=None):
|
||||
def get_max_cable_capacity_mw(cable_specs=None, voltage=VOLTAGE_LEVEL, power_factor=POWER_FACTOR):
|
||||
"""
|
||||
计算给定电缆规格中能够承载的最大功率 (单位: MW)。
|
||||
|
||||
@@ -549,6 +580,8 @@ def get_max_cable_capacity_mw(cable_specs=None):
|
||||
|
||||
参数:
|
||||
cable_specs (list, optional): 电缆规格列表。每个元素应包含 (截面积, 额定电流, 单价, 损耗系数)。
|
||||
voltage (float): 系统电压 (V), 默认 66000
|
||||
power_factor (float): 功率因数, 默认 0.95
|
||||
|
||||
返回:
|
||||
float: 最大功率承载能力 (MW)。
|
||||
@@ -576,13 +609,13 @@ def get_max_cable_capacity_mw(cable_specs=None):
|
||||
# 计算最大功率:P = √3 * U * I * cosφ
|
||||
# 这里假设降额系数为 1 (不降额)
|
||||
max_current = max_current_capacity * 1
|
||||
max_power_w = np.sqrt(3) * VOLTAGE_LEVEL * max_current * POWER_FACTOR
|
||||
max_power_w = np.sqrt(3) * voltage * max_current * power_factor
|
||||
|
||||
# 将单位从 W 转换为 MW
|
||||
return max_power_w / 1e6
|
||||
|
||||
# 5. 计算集电线路方案成本
|
||||
def evaluate_design(turbines, connections, substation, cable_specs=None, is_offshore=False, method_name="Unknown Method"):
|
||||
def evaluate_design(turbines, connections, substation, cable_specs=None, is_offshore=False, method_name="Unknown Method", voltage=VOLTAGE_LEVEL, power_factor=POWER_FACTOR):
|
||||
"""评估设计方案的总成本和损耗"""
|
||||
total_cost = 0
|
||||
total_loss = 0
|
||||
@@ -685,7 +718,7 @@ def evaluate_design(turbines, connections, substation, cable_specs=None, is_offs
|
||||
cable_specs_to_use = cable_specs
|
||||
|
||||
# 估算电流
|
||||
current = (power * 1e6) / (np.sqrt(3) * VOLTAGE_LEVEL * POWER_FACTOR)
|
||||
current = (power * 1e6) / (np.sqrt(3) * voltage * power_factor)
|
||||
|
||||
# 选择满足载流量的最小电缆
|
||||
selected_spec = None
|
||||
@@ -1055,10 +1088,12 @@ def compare_design_methods(excel_path=None, n_clusters_override=None, interactiv
|
||||
:param plot_results: 是否生成和保存对比图表
|
||||
"""
|
||||
cable_specs = None
|
||||
system_params = {}
|
||||
|
||||
if excel_path:
|
||||
print(f"正在从 {excel_path} 读取坐标数据...")
|
||||
try:
|
||||
turbines, substation, cable_specs = load_data_from_excel(excel_path)
|
||||
turbines, substation, cable_specs, system_params = load_data_from_excel(excel_path)
|
||||
scenario_title = "Offshore Wind Farm (Imported Data)"
|
||||
except Exception:
|
||||
print("回退到自动生成数据模式...")
|
||||
@@ -1070,6 +1105,10 @@ def compare_design_methods(excel_path=None, n_clusters_override=None, interactiv
|
||||
|
||||
is_offshore = True
|
||||
|
||||
voltage = system_params.get('voltage', VOLTAGE_LEVEL)
|
||||
power_factor = system_params.get('power_factor', POWER_FACTOR)
|
||||
print(f"使用的系统参数: 电压={voltage} V, 功率因数={power_factor}")
|
||||
|
||||
# 准备三种电缆方案
|
||||
# 原始 specs 是 5 元素元组: (section, capacity, resistance, cost, is_optional)
|
||||
# 下游函数期望 4 元素元组: (section, capacity, resistance, cost)
|
||||
@@ -1114,7 +1153,7 @@ def compare_design_methods(excel_path=None, n_clusters_override=None, interactiv
|
||||
|
||||
# 1. MST 方法作为基准 (使用 Scenario 1)
|
||||
mst_connections = design_with_mst(turbines, substation)
|
||||
mst_evaluation = evaluate_design(turbines, mst_connections, substation, cable_specs=specs_1, is_offshore=is_offshore, method_name="MST Method")
|
||||
mst_evaluation = evaluate_design(turbines, mst_connections, substation, cable_specs=specs_1, is_offshore=is_offshore, method_name="MST Method", voltage=voltage, power_factor=power_factor)
|
||||
|
||||
# 准备画布 2x2
|
||||
fig = None
|
||||
@@ -1152,7 +1191,7 @@ def compare_design_methods(excel_path=None, n_clusters_override=None, interactiv
|
||||
|
||||
# 计算参数
|
||||
total_power = turbines['power'].sum()
|
||||
max_cable_mw = get_max_cable_capacity_mw(cable_specs=current_specs)
|
||||
max_cable_mw = get_max_cable_capacity_mw(cable_specs=current_specs, voltage=voltage, power_factor=power_factor)
|
||||
|
||||
# 确定簇数 (针对 Base 算法)
|
||||
if n_clusters_override is not None:
|
||||
@@ -1172,11 +1211,11 @@ def compare_design_methods(excel_path=None, n_clusters_override=None, interactiv
|
||||
# --- Run 1: Base Algorithm (Capacitated Sweep) ---
|
||||
base_name = f"{name} (Base)"
|
||||
conns_base, turbines_base = design_with_capacitated_sweep(
|
||||
turbines.copy(), substation, cable_specs=current_specs
|
||||
turbines.copy(), substation, cable_specs=current_specs, voltage=voltage, power_factor=power_factor
|
||||
)
|
||||
eval_base = evaluate_design(
|
||||
turbines, conns_base, substation, cable_specs=current_specs,
|
||||
is_offshore=is_offshore, method_name=base_name
|
||||
is_offshore=is_offshore, method_name=base_name, voltage=voltage, power_factor=power_factor
|
||||
)
|
||||
|
||||
comparison_results.append({
|
||||
@@ -1192,11 +1231,11 @@ def compare_design_methods(excel_path=None, n_clusters_override=None, interactiv
|
||||
# --- Run 2: Rotational Algorithm (Optimization) ---
|
||||
rot_name = f"{name} (Rotational)"
|
||||
conns_rot, turbines_rot = design_with_rotational_sweep(
|
||||
turbines.copy(), substation, cable_specs=current_specs
|
||||
turbines.copy(), substation, cable_specs=current_specs, voltage=voltage, power_factor=power_factor
|
||||
)
|
||||
eval_rot = evaluate_design(
|
||||
turbines, conns_rot, substation, cable_specs=current_specs,
|
||||
is_offshore=is_offshore, method_name=rot_name
|
||||
is_offshore=is_offshore, method_name=rot_name, voltage=voltage, power_factor=power_factor
|
||||
)
|
||||
|
||||
comparison_results.append({
|
||||
@@ -1216,7 +1255,7 @@ def compare_design_methods(excel_path=None, n_clusters_override=None, interactiv
|
||||
)
|
||||
eval_ew = evaluate_design(
|
||||
turbines, conns_ew, substation, cable_specs=current_specs,
|
||||
is_offshore=is_offshore, method_name=ew_name
|
||||
is_offshore=is_offshore, method_name=ew_name, voltage=voltage, power_factor=power_factor
|
||||
)
|
||||
|
||||
comparison_results.append({
|
||||
|
||||
Reference in New Issue
Block a user