fix: bare except (#1159)

Bare `except:` catches SystemExit and KeyboardInterrupt, which can:
- Mask Ctrl+C handling during long optimization runs
- Hide critical system signals
- Make debugging harder

Replacement by `except Exception:` preserves the same error handling while respecting
system-level exceptions.

Co-authored-by: Milo @KeloYuan

Signed-off-by: Bobby Noelte <b0661n0e17e@gmail.com>
This commit is contained in:
Bobby Noelte
2026-07-20 01:11:33 +02:00
committed by GitHub
parent 6933b33542
commit 8bf798daeb
21 changed files with 59 additions and 59 deletions

View File

@@ -1,6 +1,6 @@
# Akkudoktor-EOS
**Version**: `v0.3.0.dev2607171715033828`
**Version**: `v0.3.0.dev2607181096091018`
<!-- pyml disable line-length -->
**Description**: This project provides a comprehensive solution for simulating and optimizing an energy system based on renewable energy sources. With a focus on photovoltaic (PV) systems, battery storage (batteries), load management (consumer requirements), heat pumps, electric vehicles, and consideration of electricity price data, this system enables forecasting and optimization of energy flow and costs over a specified period.

View File

@@ -8,7 +8,7 @@
"name": "Apache 2.0",
"url": "https://www.apache.org/licenses/LICENSE-2.0.html"
},
"version": "v0.3.0.dev2607171715033828"
"version": "v0.3.0.dev2607181096091018"
},
"paths": {
"/v1/admin/cache/clear": {

View File

@@ -33,7 +33,7 @@ def akkudoktoreos_base_branch():
# Get the current branch
try:
current_branch = repo.active_branch.name
except:
except Exception:
# Maybe detached branch that has no name
return None

View File

@@ -146,7 +146,7 @@ class HomeAssistantAdapterCommonSettings(SettingsBaseModel):
try:
adapter_eos = get_adapter()
result = adapter_eos.provider_by_id("HomeAssistant").get_homeassistant_entity_ids()
except:
except Exception:
return []
return result
@@ -157,7 +157,7 @@ class HomeAssistantAdapterCommonSettings(SettingsBaseModel):
try:
adapter_eos = get_adapter()
result = adapter_eos.provider_by_id("HomeAssistant").get_eos_solution_entity_ids()
except:
except Exception:
return []
return result
@@ -170,7 +170,7 @@ class HomeAssistantAdapterCommonSettings(SettingsBaseModel):
result = adapter_eos.provider_by_id(
"HomeAssistant"
).get_eos_device_instruction_entity_ids()
except:
except Exception:
return []
return result
@@ -256,7 +256,7 @@ class HomeAssistantAdapter(AdapterProvider):
optimization_solution_keys = self.config.optimization.keys
for key in sorted(optimization_solution_keys):
solution_entity_ids.append(self._entity_id_from_solution_key(key))
except:
except Exception:
solution_entity_ids = []
return solution_entity_ids

View File

@@ -250,7 +250,7 @@ class DataRecord(DataABC, MutableMapping):
try:
# Let getattr do the work
return self.__getattr__(key)
except:
except AttributeError:
raise KeyError(f"'{key}' not found in the record fields.")
def __setitem__(self, key: str, value: Any) -> None:
@@ -266,7 +266,7 @@ class DataRecord(DataABC, MutableMapping):
try:
# Let setattr do the work
self.__setattr__(key, value)
except:
except AttributeError:
raise KeyError(f"'{key}' is not a recognized field.")
def __delitem__(self, key: str) -> None:
@@ -280,7 +280,7 @@ class DataRecord(DataABC, MutableMapping):
"""
try:
self.__delattr__(key)
except:
except AttributeError:
raise KeyError(f"'{key}' is not a recognized field.")
def __iter__(self) -> Iterator[str]:

View File

@@ -809,7 +809,7 @@ class DatabaseRecordProtocolMixin(
self._db_load_phase = DatabaseRecordProtocolLoadPhase.NONE
try:
del self._db_initialized
except:
except Exception:
logger.debug("_db_reset_state called on uninitialized sequence")
def _db_clone_empty(self: T_DatabaseRecordProtocol) -> T_DatabaseRecordProtocol:

View File

@@ -37,7 +37,7 @@ class LoggingCommonSettings(SettingsBaseModel):
"""Computed log file path based on data output path."""
try:
path = SettingsBaseModel.config.general.data_output_path / "eos.log"
except:
except Exception:
# Config may not be fully set up
path = None
return path

View File

@@ -133,8 +133,8 @@ class PydanticModelNestedValueMixin:
try:
self._validate_path_structure(path)
pass
except:
raise ValueError(f"Path '{path}' is invalid")
except Exception as e:
raise ValueError(f"Path '{path}' is invalid: {e}")
path = path.strip("/")
# Use private data workaround
# Should be:

View File

@@ -974,7 +974,7 @@ class GeneticOptimization(OptimizationBase):
if self.optimize_ev and parameters.eauto and self.simulation.ev:
try:
penalty = self.config.optimization.genetic.penalties["ev_soc_miss"]
except:
except Exception:
# Use default
penalty = 10
logger.error(
@@ -1005,7 +1005,7 @@ class GeneticOptimization(OptimizationBase):
individuals = self.config.optimization.genetic.individuals
if individuals is None:
raise
except:
except Exception:
individuals = 300
logger.error("Individuals not configured. Using {}.", individuals)
@@ -1076,7 +1076,7 @@ class GeneticOptimization(OptimizationBase):
if generations is None:
try:
generations = self.config.optimization.genetic.generations
except:
except Exception:
generations = 400
logger.error("Generations not configured. Using {}.", generations)

View File

@@ -282,9 +282,9 @@ class GeneticOptimizationParameters(
fill_method="linear",
)
pvforecast_ac_power = (array * power_to_energy_per_interval_factor).to_list()
except:
except Exception as e:
logger.info(
"No PV forecast data available - defaulting to demo data. Parameter preparation attempt {}.",
"No PV forecast data available - defaulting to demo data. Parameter preparation attempt {}: {e}",
attempt,
)
cls.config.merge_settings_from_dict(
@@ -336,9 +336,9 @@ class GeneticOptimizationParameters(
fill_method="ffill",
)
elecprice_marketprice_wh = array.to_list()
except:
except Exception as e:
logger.info(
"No Electricity Marketprice forecast data available - defaulting to demo data. Parameter preparation attempt {}.",
"No Electricity Marketprice forecast data available - defaulting to demo data. Parameter preparation attempt {}: {e}",
attempt,
)
cls.config.elecprice.provider = "ElecPriceAkkudoktor"
@@ -353,9 +353,9 @@ class GeneticOptimizationParameters(
fill_method="ffill",
)
loadforecast_power_w = array.to_list()
except:
except Exception as e:
logger.info(
"No Load forecast data available - defaulting to demo data. Parameter preparation attempt {}.",
"No Load forecast data available - defaulting to demo data. Parameter preparation attempt {}: {e}",
attempt,
)
cls.config.merge_settings_from_dict(
@@ -379,9 +379,9 @@ class GeneticOptimizationParameters(
fill_method="ffill",
)
feed_in_tariff_wh = array.to_list()
except:
except Exception as e:
logger.info(
"No feed in tariff forecast data available - defaulting to demo data. Parameter preparation attempt {}.",
"No feed in tariff forecast data available - defaulting to demo data. Parameter preparation attempt {}: {e}",
attempt,
)
cls.config.merge_settings_from_dict(
@@ -407,9 +407,9 @@ class GeneticOptimizationParameters(
fill_method="ffill",
)
weather_temp_air = array.to_list()
except:
except Exception as e:
logger.info(
"No weather forecast data available - defaulting to demo data. Parameter preparation attempt {}.",
"No weather forecast data available - defaulting to demo data. Parameter preparation attempt {}: {e}",
attempt,
)
cls.config.weather.provider = "BrightSky"
@@ -442,9 +442,9 @@ class GeneticOptimizationParameters(
max_soc_percentage=battery_config.max_soc_percentage,
charge_rates=battery_config.charge_rates,
)
except:
except Exception as e:
logger.info(
"No battery device data available - defaulting to demo data. Parameter preparation attempt {}.",
"No battery device data available - defaulting to demo data. Parameter preparation attempt {}: {e}",
attempt,
)
cls.config.devices.batteries = [{"device_id": "battery1", "capacity_wh": 8000}]
@@ -472,7 +472,7 @@ class GeneticOptimizationParameters(
initial_soc_factor = 0.0
# genetic parameter is 0..100 as int
initial_soc_percentage = int(initial_soc_factor * 100)
except:
except Exception:
initial_soc_percentage = None
if initial_soc_percentage is None:
logger.info(
@@ -514,9 +514,9 @@ class GeneticOptimizationParameters(
min_soc_percentage=electric_vehicle_config.min_soc_percentage,
max_soc_percentage=electric_vehicle_config.max_soc_percentage,
)
except:
except Exception as e:
logger.info(
"No electric_vehicle device data available - defaulting to demo data. Parameter preparation attempt {}.",
"No electric_vehicle device data available - defaulting to demo data. Parameter preparation attempt {}: {e}",
attempt,
)
cls.config.devices.max_electric_vehicles = 1
@@ -544,7 +544,7 @@ class GeneticOptimizationParameters(
initial_soc_factor = 0.0
# genetic parameter is 0..100 as int
initial_soc_percentage = int(initial_soc_factor * 100)
except:
except Exception:
initial_soc_percentage = None
if initial_soc_percentage is None:
logger.info(
@@ -580,9 +580,9 @@ class GeneticOptimizationParameters(
dc_to_ac_efficiency=inverter_config.dc_to_ac_efficiency,
max_ac_charge_power_w=inverter_config.max_ac_charge_power_w,
)
except:
except Exception as e:
logger.info(
"No inverter device data available - defaulting to demo data. Parameter preparation attempt {}.",
"No inverter device data available - defaulting to demo data. Parameter preparation attempt {}: {e}",
attempt,
)
cls.config.devices.inverters = [
@@ -635,9 +635,9 @@ class GeneticOptimizationParameters(
duration_h=home_appliance_config.duration_h,
time_windows=home_appliance_config.time_windows,
)
except:
except Exception as e:
logger.info(
"No home appliance device data available - defaulting to demo data. Parameter preparation attempt {}.",
"No home appliance device data available - defaulting to demo data. Parameter preparation attempt {}: {e}",
attempt,
)
cls.config.devices.home_appliances = [
@@ -668,9 +668,9 @@ class GeneticOptimizationParameters(
dishwasher=home_appliance_params,
start_solution=start_solution,
)
except:
except Exception as e:
logger.info(
"Can not prepare optimization parameters - will retry. Parameter preparation attempt {}.",
"Can not prepare optimization parameters - will retry. Parameter preparation attempt {}: {e}",
attempt,
)
oparams = None

View File

@@ -100,7 +100,7 @@ class OptimizationCommonSettings(SettingsBaseModel):
"""The keys of the solution."""
try:
ems_eos = get_ems()
except:
except Exception:
# ems might not be initialized
return []

View File

@@ -16,7 +16,7 @@ def elecprice_provider_ids() -> list[str]:
"""Valid elecprice provider ids."""
try:
prediction_eos = get_prediction()
except:
except Exception:
# Prediction may not be initialized
# Return at least provider used in example
return ["ElecPriceAkkudoktor"]

View File

@@ -13,7 +13,7 @@ def feedintariff_provider_ids() -> list[str]:
"""Valid feedintariff provider ids."""
try:
prediction_eos = get_prediction()
except:
except Exception:
# Prediction may not be initialized
# Return at least provider used in example
return ["FeedInTariffFixed", "FeedInTarifImport"]

View File

@@ -40,7 +40,7 @@ class FeedInTariffFixed(FeedInTariffProvider):
feed_in_tariff = (
self.config.feedintariff.provider_settings.FeedInTariffFixed.feed_in_tariff_kwh
)
except:
except Exception:
logger.exception(error_msg)
raise ValueError(error_msg)
if feed_in_tariff is None:

View File

@@ -16,7 +16,7 @@ def load_providers() -> list[str]:
"""Valid load provider ids."""
try:
prediction_eos = get_prediction()
except:
except Exception:
# Prediction may not be initialized
# Return at least provider used in example
return ["LoadAkkudoktor", "LoadVrm", "LoadImport"]

View File

@@ -20,7 +20,7 @@ def pvforecast_provider_ids() -> list[str]:
"""Valid PV forecast providers."""
try:
prediction_eos = get_prediction()
except:
except Exception:
# Prediction may not be initialized
# Return at least provider used in example
return [

View File

@@ -14,7 +14,7 @@ def weather_provider_ids() -> list[str]:
"""Valid weather provider ids."""
try:
prediction_eos = get_prediction()
except:
except Exception:
# Prediction may not be initialized
# Return at least provider used in example
return ["WeatherImport"]

View File

@@ -528,7 +528,7 @@ def Configuration(
value_json_str: str = data.get("value", "")
try:
value = json.loads(value_json_str)
except:
except Exception:
if value_json_str in ("None", "none", "Null", "null"):
value = None
else:
@@ -602,7 +602,7 @@ def Configuration(
# find some special configuration values
try:
max_planes = int(config_details["pvforecast.max_planes"]["value"])
except:
except Exception:
max_planes = 0
logger.debug(f"max_planes: {max_planes}")
@@ -610,7 +610,7 @@ def Configuration(
homeassistant_entity_ids = json.loads(
config_details["adapter.homeassistant.homeassistant_entity_ids"]["value"]
)
except:
except Exception:
homeassistant_entity_ids = []
logger.debug(f"homeassistant_entity_ids: {homeassistant_entity_ids}")
@@ -619,7 +619,7 @@ def Configuration(
eos_solution_entity_ids = json.loads(
config_details["adapter.homeassistant.eos_solution_entity_ids"]["value"]
)
except:
except Exception:
eos_solution_entity_ids = []
logger.debug(f"eos_solution_entity_ids {eos_solution_entity_ids}")
@@ -628,14 +628,14 @@ def Configuration(
eos_device_instruction_entity_ids = json.loads(
config_details["adapter.homeassistant.eos_device_instruction_entity_ids"]["value"]
)
except:
except Exception:
eos_device_instruction_entity_ids = []
logger.debug(f"eos_device_instruction_entity_ids {eos_device_instruction_entity_ids}")
devices_measurement_keys = []
try:
devices_measurement_keys = json.loads(config_details["devices.measurement_keys"]["value"])
except:
except Exception:
devices_measurement_keys = []
logger.debug(f"devices_measurement_keys {devices_measurement_keys}")
@@ -691,7 +691,7 @@ def Configuration(
# Special configuration for prediction provider setting
try:
provider_ids = json.loads(config_details[config["name"] + "s"]["value"])
except:
except Exception:
provider_ids = []
if config["type"].startswith("Optional[list"):
update_form_factory = make_config_update_list_form(provider_ids)

View File

@@ -521,10 +521,10 @@ def fastapi_config_file_put() -> ConfigEOS:
try:
get_config().to_config_file()
return get_config()
except:
except Exception as e:
raise HTTPException(
status_code=404,
detail=f"Cannot save configuration to file '{get_config().config_file_path}'.",
detail=f"Cannot save configuration to file '{get_config().config_file_path}': {e}",
)

View File

@@ -416,8 +416,8 @@ def _parse_time_string(time_str: str, default_date: pendulum.Date = None) -> pen
# Try to parse as a standard timezone name
try:
timezone_info = pendulum.timezone(timezone_str)
except:
raise ValueError(f"Unknown timezone: {timezone_str}")
except Exception as e:
raise ValueError(f"Unknown timezone: {timezone_str}: {e}")
elif re.match(r"[+-]\d{2}:?\d{2}", timezone_str):
# Handle offset format like +05:30, -08:00, +0530, -0800
clean_tz = timezone_str.replace(":", "")

View File

@@ -44,7 +44,7 @@ def caplog(caplog: LogCaptureFixture):
yield caplog
try:
logger.remove(handler_id)
except:
except Exception:
# May already be deleted
pass
@@ -57,7 +57,7 @@ def reportlog(pytestconfig):
yield
try:
logger.remove(handler_id)
except:
except Exception:
# May already be deleted
pass