run
Главный цикл приложения e-house.
Инициализирует все компоненты (ассистенты, контроллеры, источники данных, мессенджеры) и запускает их в бесконечном цикле. Периодически проверяет изменения в конфигурационном файле и перезагружает компоненты при необходимости.
1#!/usr/bin/env python3 2""" 3Главный цикл приложения e-house. 4 5Инициализирует все компоненты (ассистенты, контроллеры, источники данных, 6мессенджеры) и запускает их в бесконечном цикле. Периодически проверяет 7изменения в конфигурационном файле и перезагружает компоненты при 8необходимости. 9""" 10 11import copy 12import os 13import sys 14import time 15 16from e_lib.assistants import LangfuseCleanerAssistant, ScheduledAssistant 17from e_lib.config import Config 18from e_lib.time_utils import format_time 19from langfuse import observe 20from loguru import logger 21 22from Assistants.climate import ClimateAssistant 23from Assistants.dehumidifier import DehumidifierAssistant 24from Assistants.dog_heater import DogHeaterAssistant 25from Assistants.voltage import VoltageAssistant 26from Controllers.climate import ClimateController 27from Controllers.dehumidifier import DehumidifierController 28from Messengers.telegram import TelegramBot, TelegramTimeouts 29 30config = Config("configs/config.yml") 31 32from Assistants import DogWaterAssistant 33from Controllers.smart_plug import SmartPlugController 34from DataSources.openweather import OpenWeatherDataSource 35 36 37APP_VERSION = os.getenv("PRODUCTS_VERSION", "dev") 38 39 40def stop_all(assistants): 41 """Останавливает всех ассистентов. 42 43 Вызывает метод stop() у каждого ассистента в обратном порядке. 44 45 Args: 46 assistants: Список ассистентов для остановки. 47 """ 48 for assistant in reversed(assistants): 49 if hasattr(assistant, "stop") and callable(assistant.stop): 50 assistant.stop() 51 52 53def start_all(assistants): 54 """Запускает всех ассистентов. 55 56 Вызывает метод start() у каждого ассистента. 57 58 Args: 59 assistants: Список ассистентов для запуска. 60 """ 61 for assistant in assistants: 62 if hasattr(assistant, "start") and callable(assistant.start): 63 assistant.start() 64 65 66def init_logger(): 67 """Инициализация логгера""" 68 69 logger.remove() # удаляем стандартный обработчик 70 # Добавляем обработчик с поддержкой UTF-8 71 logger.add( 72 sys.stderr, 73 level=config.data["General"]["Logger"]["Level"], 74 # format="{time:YYYY-MM-DD HH:mm:ss} - {level} - {name} - {message}", 75 colorize=True, 76 ) 77 78 logger.debug("Логгер инициализирован") 79 80 81@observe(name="Инициализация компонентов") 82def init_components(): 83 """Инициализация компонентов""" 84 init_logger() 85 86 assistants = [] 87 bot = None 88 89 if config.data["Messengers"]["Telegram"]["ENABLED"]: 90 telegram_bot = TelegramBot( 91 config.data["Messengers"]["Telegram"]["NAME"], 92 os.getenv("TELEGRAM_TOKEN"), 93 config.data["Messengers"]["Telegram"]["CHAT_ID"], 94 TelegramTimeouts( 95 config.data["Messengers"]["Telegram"]["TIMEOUTS"]["REQUEST"], 96 config.data["Messengers"]["Telegram"]["TIMEOUTS"]["POLLING"], 97 ), 98 ) 99 assistants.append(telegram_bot) 100 bot = telegram_bot 101 logger.info( 102 f'Мессенджер "{config.data["Messengers"]["Telegram"]["NAME"]}" включен' 103 ) 104 105 # Initialize devices and data sources 106 smart_plug = SmartPlugController( 107 config.data["Devices"]["SmartPlug"]["DEVICE_ID"], 108 os.getenv("YANDEX_TOKEN"), 109 round_digits=( 110 config.data.get("Devices", {}) 111 .get("SmartPlug", {}) 112 .get("VOLTAGE_ROUNDING", 0), 113 config.data.get("Devices", {}) 114 .get("SmartPlug", {}) 115 .get("AMPERAGE_ROUNDING", 0), 116 config.data.get("Devices", {}) 117 .get("SmartPlug", {}) 118 .get("CONSUMPTION_ROUNDING", 0), 119 ), 120 state_retry_count=config.data.get("Devices", {}) 121 .get("SmartPlug", {}) 122 .get("STATE_RETRY_COUNT", 3), 123 state_retry_delay=config.data.get("Devices", {}) 124 .get("SmartPlug", {}) 125 .get("STATE_RETRY_DELAY", 2), 126 ) 127 openweather = OpenWeatherDataSource( 128 os.getenv("OPENWEATHER_API_KEY"), config.data["OpenWeather"]["CITY"] 129 ) 130 131 temp_controller = ClimateController( 132 config.data["Devices"]["ClimateSensor"]["DEVICE_ID"], 133 os.getenv("YANDEX_TOKEN"), 134 round_digits=( 135 config.data.get("Devices", {}).get("ClimateSensor", {}).get("ROUNDING", 0), 136 ), 137 state_retry_count=config.data.get("Devices", {}) 138 .get("ClimateSensor", {}) 139 .get("STATE_RETRY_COUNT", 3), 140 state_retry_delay=config.data.get("Devices", {}) 141 .get("ClimateSensor", {}) 142 .get("STATE_RETRY_DELAY", 2), 143 ) 144 145 dog_climate = ClimateController( 146 config.data["Devices"]["DogClimateSensor"]["DEVICE_ID"], 147 os.getenv("YANDEX_TOKEN"), 148 round_digits=( 149 config.data.get("Devices", {}) 150 .get("DogClimateSensor", {}) 151 .get("ROUNDING", 0), 152 ), 153 state_retry_count=config.data.get("Devices", {}) 154 .get("DogClimateSensor", {}) 155 .get("STATE_RETRY_COUNT", 3), 156 state_retry_delay=config.data.get("Devices", {}) 157 .get("DogClimateSensor", {}) 158 .get("STATE_RETRY_DELAY", 2), 159 ) 160 161 dehumidifier = DehumidifierController( 162 config.data["Devices"]["Dehumidifier"]["DEVICE_ID"], 163 os.getenv("YANDEX_TOKEN"), 164 state_retry_count=config.data.get("Devices", {}) 165 .get("Dehumidifier", {}) 166 .get("STATE_RETRY_COUNT", 3), 167 state_retry_delay=config.data.get("Devices", {}) 168 .get("Dehumidifier", {}) 169 .get("STATE_RETRY_DELAY", 2), 170 ) 171 172 # Initialize assistants based on config 173 if config.data["Assistants"]["DogWater"]["ENABLED"]: 174 dog_water = DogWaterAssistant( 175 config.data["Assistants"]["DogWater"]["NAME"], 176 smart_plug, 177 openweather, 178 config.data["Assistants"]["DogWater"]["TEMP_THRESHOLD"], 179 bot, 180 ) 181 dog_water_scheduler = ScheduledAssistant( 182 dog_water, 183 config.data["Assistants"]["DogWater"]["CHECK_INTERVAL"], 184 logger=logger, 185 ) 186 assistants.append(dog_water_scheduler) 187 logger.info( 188 f'Ассистент "{config.data["Assistants"]["DogWater"]["NAME"]}" включен' 189 ) 190 191 if config.data["Assistants"]["Voltage"]["ENABLED"]: 192 voltage = VoltageAssistant( 193 config.data["Assistants"]["Voltage"]["NAME"], 194 smart_plug, 195 config.data.get("Assistants", {}) 196 .get("Voltage", {}) 197 .get("VOLTAGE_THRESHOLD_LOW", 200), 198 config.data.get("Assistants", {}) 199 .get("Voltage", {}) 200 .get("VOLTAGE_THRESHOLD_HIGH", 250), 201 config.data.get("Assistants", {}) 202 .get("Voltage", {}) 203 .get("VOLTAGE_ROUNDING", 0), 204 bot, 205 ) 206 voltage_scheduler = ScheduledAssistant( 207 voltage, 208 config.data["Assistants"]["Voltage"]["CHECK_INTERVAL"], 209 logger=logger, 210 ) 211 assistants.append(voltage_scheduler) 212 logger.info( 213 f'Ассистент "{config.data["Assistants"]["Voltage"]["NAME"]}" включен' 214 ) 215 216 if config.data["Assistants"]["Temperature"]["ENABLED"]: 217 temperature = ClimateAssistant( 218 config.data["Assistants"]["Temperature"]["NAME"], 219 temp_controller, 220 config.data.get("Assistants", {}) 221 .get("Temperature", {}) 222 .get("TEMP_THRESHOLD_LOW", 23), 223 config.data.get("Assistants", {}) 224 .get("Temperature", {}) 225 .get("TEMP_THRESHOLD_HIGH", 25), 226 config.data.get("Assistants", {}) 227 .get("Temperature", {}) 228 .get("HUMIDITY_THRESHOLD_LOW", 25), 229 config.data.get("Assistants", {}) 230 .get("Temperature", {}) 231 .get("HUMIDITY_THRESHOLD_HIGH", 50), 232 config.data.get("Assistants", {}).get("Temperature", {}).get("ROUNDING", 0), 233 bot, 234 ) 235 temp_scheduler = ScheduledAssistant( 236 temperature, 237 config.data["Assistants"]["Temperature"]["CHECK_INTERVAL"], 238 logger=logger, 239 ) 240 assistants.append(temp_scheduler) 241 logger.info( 242 f'Ассистент "{config.data["Assistants"]["Temperature"]["NAME"]}" включен' 243 ) 244 245 if config.data["Assistants"]["LangfuseCleaner"]["ENABLED"]: 246 lf_cleaner = LangfuseCleanerAssistant( 247 project_slug="e-house", 248 period=config.data.get("Assistants", {}) 249 .get("LangfuseCleaner", {}) 250 .get("CLEAN_PERIOD", 1), 251 logger=logger, 252 ) 253 lf_cleaner_scheduler = ScheduledAssistant( 254 lf_cleaner, 255 config.data.get("Assistants", {}) 256 .get("LangfuseCleaner", {}) 257 .get("SCHEDULE_INTERVAL", 60), 258 ) 259 assistants.append(lf_cleaner_scheduler) 260 logger.info( 261 f'Ассистент "{config.data["Assistants"]["LangfuseCleaner"]["NAME"]}" включен' 262 ) 263 264 if config.data["Assistants"]["DogHeater"]["ENABLED"]: 265 dog_heater = DogHeaterAssistant( 266 config.data["Assistants"]["DogHeater"]["NAME"], 267 smart_plug, 268 dog_climate, 269 config.data["Assistants"]["DogHeater"]["TEMP_THRESHOLD"], 270 bot, 271 ) 272 dog_heater_scheduler = ScheduledAssistant( 273 dog_heater, 274 config.data["Assistants"]["DogHeater"]["CHECK_INTERVAL"], 275 logger=logger, 276 ) 277 assistants.append(dog_heater_scheduler) 278 logger.info( 279 f'Ассистент "{config.data["Assistants"]["DogHeater"]["NAME"]}" включен' 280 ) 281 282 if config.data["Assistants"]["Dehumidifier"]["ENABLED"]: 283 dehumidifier_assistant = DehumidifierAssistant( 284 config.data["Assistants"]["Dehumidifier"]["NAME"], 285 dehumidifier, 286 config.data["Assistants"]["Dehumidifier"]["HUMIDITY_THRESHOLD_HIGH"], 287 config.data["Assistants"]["Dehumidifier"].get("HUMIDITY_THRESHOLD_LOW", 50), 288 bot, 289 ) 290 dehumidifier_scheduler = ScheduledAssistant( 291 dehumidifier_assistant, 292 config.data["Assistants"]["Dehumidifier"]["CHECK_INTERVAL"], 293 logger=logger, 294 ) 295 assistants.append(dehumidifier_scheduler) 296 logger.info( 297 f'Ассистент "{config.data["Assistants"]["Dehumidifier"]["NAME"]}" включен' 298 ) 299 300 return assistants 301 302 303def main(): 304 """Основная функция приложения. 305 306 Инициализирует компоненты, запускает их и входит в бесконечный цикл. 307 В цикле проверяет изменения конфигурации и при необходимости 308 перезагружает ассистентов. Обрабатывает KeyboardInterrupt и 309 неожиданные ошибки. 310 """ 311 312 products_log = None 313 try: 314 from e_lib.product_log import ProductsLog 315 316 products_log = ProductsLog("e-house", APP_VERSION, logger=logger) 317 products_log.post_started() 318 except Exception as e: 319 logger.warning(f"ProductsLog: {e}") 320 321 assistants = [] 322 try: 323 logger.info( 324 "Интервал перезагрузки config.yml: " 325 + format_time(config.data["General"]["RELOAD_TIMEOUT"]) 326 ) 327 assistants = init_components() 328 start_all(assistants) 329 330 # tracer.end_span(span) 331 # tracer.flush() 332 333 while True: 334 old_config = copy.deepcopy(config.data) 335 config.load() 336 if config.data != old_config: 337 try: 338 stop_all(assistants) 339 new_assistants = init_components() 340 start_all(new_assistants) 341 except (OSError, RuntimeError, ValueError, KeyError, TypeError) as err: 342 logger.error( 343 f"Не удалось перезапустить ассистентов: {err}", exc_info=True 344 ) 345 start_all(assistants) 346 time.sleep(config.data["General"]["RELOAD_TIMEOUT"]) 347 continue 348 assistants = new_assistants 349 logger.debug("config.yml изменен, перезагружен") 350 time.sleep(config.data["General"]["RELOAD_TIMEOUT"]) 351 352 except KeyboardInterrupt: 353 stop_all(assistants) 354 logger.info("Работа скрипта остановлена пользователем") 355 try: 356 if products_log: 357 products_log.post_shutdown() 358 except Exception as e: 359 logger.warning(f"ProductsLog: {e}") 360 except (OSError, RuntimeError, ValueError, KeyError, TypeError) as e: 361 logger.error(f"Неожиданная ошибка: {e}") 362 363 364if __name__ == "__main__": 365 main()
41def stop_all(assistants): 42 """Останавливает всех ассистентов. 43 44 Вызывает метод stop() у каждого ассистента в обратном порядке. 45 46 Args: 47 assistants: Список ассистентов для остановки. 48 """ 49 for assistant in reversed(assistants): 50 if hasattr(assistant, "stop") and callable(assistant.stop): 51 assistant.stop()
Останавливает всех ассистентов.
Вызывает метод stop() у каждого ассистента в обратном порядке.
Args: assistants: Список ассистентов для остановки.
54def start_all(assistants): 55 """Запускает всех ассистентов. 56 57 Вызывает метод start() у каждого ассистента. 58 59 Args: 60 assistants: Список ассистентов для запуска. 61 """ 62 for assistant in assistants: 63 if hasattr(assistant, "start") and callable(assistant.start): 64 assistant.start()
Запускает всех ассистентов.
Вызывает метод start() у каждого ассистента.
Args: assistants: Список ассистентов для запуска.
67def init_logger(): 68 """Инициализация логгера""" 69 70 logger.remove() # удаляем стандартный обработчик 71 # Добавляем обработчик с поддержкой UTF-8 72 logger.add( 73 sys.stderr, 74 level=config.data["General"]["Logger"]["Level"], 75 # format="{time:YYYY-MM-DD HH:mm:ss} - {level} - {name} - {message}", 76 colorize=True, 77 ) 78 79 logger.debug("Логгер инициализирован")
Инициализация логгера
82@observe(name="Инициализация компонентов") 83def init_components(): 84 """Инициализация компонентов""" 85 init_logger() 86 87 assistants = [] 88 bot = None 89 90 if config.data["Messengers"]["Telegram"]["ENABLED"]: 91 telegram_bot = TelegramBot( 92 config.data["Messengers"]["Telegram"]["NAME"], 93 os.getenv("TELEGRAM_TOKEN"), 94 config.data["Messengers"]["Telegram"]["CHAT_ID"], 95 TelegramTimeouts( 96 config.data["Messengers"]["Telegram"]["TIMEOUTS"]["REQUEST"], 97 config.data["Messengers"]["Telegram"]["TIMEOUTS"]["POLLING"], 98 ), 99 ) 100 assistants.append(telegram_bot) 101 bot = telegram_bot 102 logger.info( 103 f'Мессенджер "{config.data["Messengers"]["Telegram"]["NAME"]}" включен' 104 ) 105 106 # Initialize devices and data sources 107 smart_plug = SmartPlugController( 108 config.data["Devices"]["SmartPlug"]["DEVICE_ID"], 109 os.getenv("YANDEX_TOKEN"), 110 round_digits=( 111 config.data.get("Devices", {}) 112 .get("SmartPlug", {}) 113 .get("VOLTAGE_ROUNDING", 0), 114 config.data.get("Devices", {}) 115 .get("SmartPlug", {}) 116 .get("AMPERAGE_ROUNDING", 0), 117 config.data.get("Devices", {}) 118 .get("SmartPlug", {}) 119 .get("CONSUMPTION_ROUNDING", 0), 120 ), 121 state_retry_count=config.data.get("Devices", {}) 122 .get("SmartPlug", {}) 123 .get("STATE_RETRY_COUNT", 3), 124 state_retry_delay=config.data.get("Devices", {}) 125 .get("SmartPlug", {}) 126 .get("STATE_RETRY_DELAY", 2), 127 ) 128 openweather = OpenWeatherDataSource( 129 os.getenv("OPENWEATHER_API_KEY"), config.data["OpenWeather"]["CITY"] 130 ) 131 132 temp_controller = ClimateController( 133 config.data["Devices"]["ClimateSensor"]["DEVICE_ID"], 134 os.getenv("YANDEX_TOKEN"), 135 round_digits=( 136 config.data.get("Devices", {}).get("ClimateSensor", {}).get("ROUNDING", 0), 137 ), 138 state_retry_count=config.data.get("Devices", {}) 139 .get("ClimateSensor", {}) 140 .get("STATE_RETRY_COUNT", 3), 141 state_retry_delay=config.data.get("Devices", {}) 142 .get("ClimateSensor", {}) 143 .get("STATE_RETRY_DELAY", 2), 144 ) 145 146 dog_climate = ClimateController( 147 config.data["Devices"]["DogClimateSensor"]["DEVICE_ID"], 148 os.getenv("YANDEX_TOKEN"), 149 round_digits=( 150 config.data.get("Devices", {}) 151 .get("DogClimateSensor", {}) 152 .get("ROUNDING", 0), 153 ), 154 state_retry_count=config.data.get("Devices", {}) 155 .get("DogClimateSensor", {}) 156 .get("STATE_RETRY_COUNT", 3), 157 state_retry_delay=config.data.get("Devices", {}) 158 .get("DogClimateSensor", {}) 159 .get("STATE_RETRY_DELAY", 2), 160 ) 161 162 dehumidifier = DehumidifierController( 163 config.data["Devices"]["Dehumidifier"]["DEVICE_ID"], 164 os.getenv("YANDEX_TOKEN"), 165 state_retry_count=config.data.get("Devices", {}) 166 .get("Dehumidifier", {}) 167 .get("STATE_RETRY_COUNT", 3), 168 state_retry_delay=config.data.get("Devices", {}) 169 .get("Dehumidifier", {}) 170 .get("STATE_RETRY_DELAY", 2), 171 ) 172 173 # Initialize assistants based on config 174 if config.data["Assistants"]["DogWater"]["ENABLED"]: 175 dog_water = DogWaterAssistant( 176 config.data["Assistants"]["DogWater"]["NAME"], 177 smart_plug, 178 openweather, 179 config.data["Assistants"]["DogWater"]["TEMP_THRESHOLD"], 180 bot, 181 ) 182 dog_water_scheduler = ScheduledAssistant( 183 dog_water, 184 config.data["Assistants"]["DogWater"]["CHECK_INTERVAL"], 185 logger=logger, 186 ) 187 assistants.append(dog_water_scheduler) 188 logger.info( 189 f'Ассистент "{config.data["Assistants"]["DogWater"]["NAME"]}" включен' 190 ) 191 192 if config.data["Assistants"]["Voltage"]["ENABLED"]: 193 voltage = VoltageAssistant( 194 config.data["Assistants"]["Voltage"]["NAME"], 195 smart_plug, 196 config.data.get("Assistants", {}) 197 .get("Voltage", {}) 198 .get("VOLTAGE_THRESHOLD_LOW", 200), 199 config.data.get("Assistants", {}) 200 .get("Voltage", {}) 201 .get("VOLTAGE_THRESHOLD_HIGH", 250), 202 config.data.get("Assistants", {}) 203 .get("Voltage", {}) 204 .get("VOLTAGE_ROUNDING", 0), 205 bot, 206 ) 207 voltage_scheduler = ScheduledAssistant( 208 voltage, 209 config.data["Assistants"]["Voltage"]["CHECK_INTERVAL"], 210 logger=logger, 211 ) 212 assistants.append(voltage_scheduler) 213 logger.info( 214 f'Ассистент "{config.data["Assistants"]["Voltage"]["NAME"]}" включен' 215 ) 216 217 if config.data["Assistants"]["Temperature"]["ENABLED"]: 218 temperature = ClimateAssistant( 219 config.data["Assistants"]["Temperature"]["NAME"], 220 temp_controller, 221 config.data.get("Assistants", {}) 222 .get("Temperature", {}) 223 .get("TEMP_THRESHOLD_LOW", 23), 224 config.data.get("Assistants", {}) 225 .get("Temperature", {}) 226 .get("TEMP_THRESHOLD_HIGH", 25), 227 config.data.get("Assistants", {}) 228 .get("Temperature", {}) 229 .get("HUMIDITY_THRESHOLD_LOW", 25), 230 config.data.get("Assistants", {}) 231 .get("Temperature", {}) 232 .get("HUMIDITY_THRESHOLD_HIGH", 50), 233 config.data.get("Assistants", {}).get("Temperature", {}).get("ROUNDING", 0), 234 bot, 235 ) 236 temp_scheduler = ScheduledAssistant( 237 temperature, 238 config.data["Assistants"]["Temperature"]["CHECK_INTERVAL"], 239 logger=logger, 240 ) 241 assistants.append(temp_scheduler) 242 logger.info( 243 f'Ассистент "{config.data["Assistants"]["Temperature"]["NAME"]}" включен' 244 ) 245 246 if config.data["Assistants"]["LangfuseCleaner"]["ENABLED"]: 247 lf_cleaner = LangfuseCleanerAssistant( 248 project_slug="e-house", 249 period=config.data.get("Assistants", {}) 250 .get("LangfuseCleaner", {}) 251 .get("CLEAN_PERIOD", 1), 252 logger=logger, 253 ) 254 lf_cleaner_scheduler = ScheduledAssistant( 255 lf_cleaner, 256 config.data.get("Assistants", {}) 257 .get("LangfuseCleaner", {}) 258 .get("SCHEDULE_INTERVAL", 60), 259 ) 260 assistants.append(lf_cleaner_scheduler) 261 logger.info( 262 f'Ассистент "{config.data["Assistants"]["LangfuseCleaner"]["NAME"]}" включен' 263 ) 264 265 if config.data["Assistants"]["DogHeater"]["ENABLED"]: 266 dog_heater = DogHeaterAssistant( 267 config.data["Assistants"]["DogHeater"]["NAME"], 268 smart_plug, 269 dog_climate, 270 config.data["Assistants"]["DogHeater"]["TEMP_THRESHOLD"], 271 bot, 272 ) 273 dog_heater_scheduler = ScheduledAssistant( 274 dog_heater, 275 config.data["Assistants"]["DogHeater"]["CHECK_INTERVAL"], 276 logger=logger, 277 ) 278 assistants.append(dog_heater_scheduler) 279 logger.info( 280 f'Ассистент "{config.data["Assistants"]["DogHeater"]["NAME"]}" включен' 281 ) 282 283 if config.data["Assistants"]["Dehumidifier"]["ENABLED"]: 284 dehumidifier_assistant = DehumidifierAssistant( 285 config.data["Assistants"]["Dehumidifier"]["NAME"], 286 dehumidifier, 287 config.data["Assistants"]["Dehumidifier"]["HUMIDITY_THRESHOLD_HIGH"], 288 config.data["Assistants"]["Dehumidifier"].get("HUMIDITY_THRESHOLD_LOW", 50), 289 bot, 290 ) 291 dehumidifier_scheduler = ScheduledAssistant( 292 dehumidifier_assistant, 293 config.data["Assistants"]["Dehumidifier"]["CHECK_INTERVAL"], 294 logger=logger, 295 ) 296 assistants.append(dehumidifier_scheduler) 297 logger.info( 298 f'Ассистент "{config.data["Assistants"]["Dehumidifier"]["NAME"]}" включен' 299 ) 300 301 return assistants
Инициализация компонентов
304def main(): 305 """Основная функция приложения. 306 307 Инициализирует компоненты, запускает их и входит в бесконечный цикл. 308 В цикле проверяет изменения конфигурации и при необходимости 309 перезагружает ассистентов. Обрабатывает KeyboardInterrupt и 310 неожиданные ошибки. 311 """ 312 313 products_log = None 314 try: 315 from e_lib.product_log import ProductsLog 316 317 products_log = ProductsLog("e-house", APP_VERSION, logger=logger) 318 products_log.post_started() 319 except Exception as e: 320 logger.warning(f"ProductsLog: {e}") 321 322 assistants = [] 323 try: 324 logger.info( 325 "Интервал перезагрузки config.yml: " 326 + format_time(config.data["General"]["RELOAD_TIMEOUT"]) 327 ) 328 assistants = init_components() 329 start_all(assistants) 330 331 # tracer.end_span(span) 332 # tracer.flush() 333 334 while True: 335 old_config = copy.deepcopy(config.data) 336 config.load() 337 if config.data != old_config: 338 try: 339 stop_all(assistants) 340 new_assistants = init_components() 341 start_all(new_assistants) 342 except (OSError, RuntimeError, ValueError, KeyError, TypeError) as err: 343 logger.error( 344 f"Не удалось перезапустить ассистентов: {err}", exc_info=True 345 ) 346 start_all(assistants) 347 time.sleep(config.data["General"]["RELOAD_TIMEOUT"]) 348 continue 349 assistants = new_assistants 350 logger.debug("config.yml изменен, перезагружен") 351 time.sleep(config.data["General"]["RELOAD_TIMEOUT"]) 352 353 except KeyboardInterrupt: 354 stop_all(assistants) 355 logger.info("Работа скрипта остановлена пользователем") 356 try: 357 if products_log: 358 products_log.post_shutdown() 359 except Exception as e: 360 logger.warning(f"ProductsLog: {e}") 361 except (OSError, RuntimeError, ValueError, KeyError, TypeError) as e: 362 logger.error(f"Неожиданная ошибка: {e}")
Основная функция приложения.
Инициализирует компоненты, запускает их и входит в бесконечный цикл. В цикле проверяет изменения конфигурации и при необходимости перезагружает ассистентов. Обрабатывает KeyboardInterrupt и неожиданные ошибки.