Добрый день, уважаемые знатоки. Работаю над скриптом, использующим сетевое реле для перезагрузки видеокамер, и столкнулся с вопросом о реализации счетчика. Я проверяю доступность камер с помощью цикличного пинга, и мне нужно создать элегантный счетчик, который, например, будет запускать функцию перезагрузки после 5 неудачных попыток, а также отслеживать общее количество перезагрузок. Я понимаю, что это можно сделать с использованием глобальных переменных, но во время поиска информации наткнулся на мнение, что глобальные переменные — это плохо, без пояснений причин. С учетом моего опыта, мне бы хотелось понять, как можно реализовать эту задачу корректно и согласно лучшим практикам. Вот пример метода, который я использую: <pre><code class="python">IP12 = '192.168.0.100' IP13 = '192.168.0.101' RODOS12 = '192.168.1.100' RODOS13 = '192.168.1.101' def cameras_checker(self): while True: r_dict = {'Купол 12': IP12, 'Купол 13': IP13} for key, val in r_dict.items(): cmd = f'ping {val} -n 1 -w 100' response = subprocess.call(cmd, stdout=subprocess.DEVNULL) if not response: print(f'Camera {key} - OK') счетчик неудач 12 или 13 купола = 0 # Обнуляем при успешном пинге else: if key == 'Купол 12': счетчик неудач 12 купола += 1 # Увеличиваем счетчик для 12 купола print(f'Camera {key} - Died') if счетчик неудач 12 купола == 5: self.cameras_reboot(RODOS12) else: счетчик неудач 13 купола += 1 # Увеличиваем счетчик для 13 купола print(f'Camera {key} - Died') </code></pre> Как можно организовать эту логику без использования глобальных переменных?
Для решения вашей задачи без использования глобальных переменных вы можете использовать класс для инкапсуляции состояния счетчиков и логики работы с камерами. Таким образом, состояние (например, количество неудачных попыток и количество перезагрузок) будет связано с экземпляром класса. Вот пример, как это можно реализовать: ```python import subprocess import time class CameraManager: def __init__(self, camera_ips, reboot_ips): self.camera_ips = camera_ips # Словарь с именами камер и их IP self.reboot_ips = reboot_ips # Словарь с именами камер и IP для перезагрузки self.failure_counters = {key: 0 for key in camera_ips.keys()} # Счетчики неудачных попыток self.reboot_count = 0 # Общее количество перезагрузок def ping_camera(self, ip): cmd = f'ping {ip} -n 1 -w 100' return subprocess.call(cmd, stdout=subprocess.DEVNULL) == 0 def cameras_checker(self): while True: for key, val in self.camera_ips.items(): if self.ping_camera(val): print(f'Camera {key} - OK') self.failure_counters[key] = 0 # Обнуляем счетчик при успешном пинге else: print(f'Camera {key} - Died') self.failure_counters[key] += 1 # Увеличиваем счетчик для камеры if self.failure_counters[key] == 5: self.reboot_camera(key) time.sleep(1) # Задержка между проверками def reboot_camera(self, camera_name): if camera_name in self.reboot_ips: print(f'Rebooting {camera_name}...') # Здесь можно добавить код для отправки команды на перезагрузку self.reboot_count += 1 # Увеличиваем общий счетчик перезагрузок print(f'Total reboots: {self.reboot_count}') self.failure_counters[camera_name] = 0 # Обнуляем счетчик неудач после перезагрузки if __name__ == "__main__": camera_ips = { 'Купол 12': '192.168.0.100', 'Купол 13': '192.168.0.101', } reboot_ips = { 'Купол 12': '192.168.1.100', 'Купол 13': '192.168.1.101', } manager = CameraManager(camera_ips, reboot_ips) manager.cameras_checker() ``` ### Объяснение реализации: 1. **Класс `CameraManager`**: - Инициализируется с двумя словарями: один для IP камер и другой для IP реле перезагрузки. - Содержит `failure_counters` для отслеживания неудачных попыток пинга каждой камеры. - Также содержит `reboot_count` для подсчета общего количества перезагрузок. 2. **Метод `ping_camera`**: - Определяет, доступна ли камера, возвращая `True` или `False`. 3. **Метод `cameras_checker`**: - Работает в бесконечном цикле. Пингует каждую камеру и обновляет соответствующий счетчик. - Если после 5 неудачных попыток, инициируется перезагрузка с помощью метода `reboot_camera`. 4. **Метод `reboot_camera`**: - Здесь можно добавить логику для фактической перезагрузки камеры и обновления счетчиков. ### Преимущества данного подхода: - Избегая глобальных переменных, вы улучшаете читаемость и поддержку кода. - Инкапсуляция состояния в классе позволяет лучше управлять состоянием приложения. - Код легче тестировать и расширять в будущем.
Как-то так
def cameras_checker(self): cameras = [ {'name': 'Купол 12', 'ip': IP12, 'rebootIp': RODOS12, 'fails': 0}, {'name': 'Купол 13', 'ip': IP13, 'rebootIp': RODOS13, 'fails': 0}, ] while True: for camera in cameras: cmd = f"ping {camera['ip']} -n 1 -w 100" response = subprocesscall(cmd, stdout=subprocess.DEVNUL) if not response: print(f'Camera {camera['name']} ok') camera['fails'] = 0 else: camera['fails'] += 1 print(f"Camera {camera['name']} died") if camera['fails'] = 5: self.cameras_reboot(camera['rebootIp']) sleep(5)
По феншую и правильно по хорошему бы реализовать класс, в котором будешь хранить состояние счётчиков
import subprocess from time import sleep class CameraMonitor: def __init__(self): self.IP12 = '192.168.0.100' self.IP13 = '192.168.0.101' self.RODOS12 = '192.168.1.100' self.RODOS13 = '192.168.1.101' self.fail_count = {'Купол 12': 0, 'Купол 13': 0} self.reboot_count = {'Купол 12': 0, 'Купол 13': 0} def ping_camera(self, ip): cmd = f'ping {ip} -n 1 -w 100' response = subprocess.call(cmd, stdout=subprocess.DEVNULL) return response == 0 def cameras_checker(self): r_dict = {'Купол 12': self.IP12, 'Купол 13': self.IP13} while True: for camera, ip in r_dict.items(): if self.ping_camera(ip): print(f'Camera {camera} - OK') self.fail_count[camera] = 0 else: self.fail_count[camera] += 1 print(f'Camera {camera} - Died') if self.fail_count[camera] >= 5: self.cameras_reboot(camera) sleep(5) def cameras_reboot(self, camera): if camera == 'Купол 12': ip = self.RODOS12 else: ip = self.RODOS13 self.reboot_count[camera] += 1 print(f'Rebooting {camera} at IP {ip}') def info(self): for camera, count in self.reboot_count.items(): print(f'Перезагрузок {camera}: {count}') if __name__ == "__main__": monitor = CameraMonitor() monitor.cameras_checker()