отслеживать (не) успешную инициализацию объекта - PullRequest
0 голосов
/ 07 марта 2019

У меня есть скрипт на python, который управляет различными тестовыми инструментами (генератор сигналов, усилитель, анализатор спектра ...) для автоматизации теста.

Эти устройства обмениваются данными через Ethernet или последовательный порт с ПК, на котором выполняется этот скрипт на python.

Я написал класс для каждого устройства, которое я использую.Сценарий начинается с инициализации экземпляра этих классов.Примерно так:

multimeter = Multimeter(192.168.1.5,5025)
amplifier = Amplifier(192.168.1.9,5025)
stirrer = Stirrer('COM4',9600)
.....

Это может ошибаться во многих отношениях (батарея разряжена, устройство не включено, кабель не подключен ...)

Возможно отловить ошибки с помощьюtry / catch - try-exc:

try:
    multimeter = Multimeter(192.168.1.5,5025)
    amplifier = Amplifier(192.168.1.9,5025)
    stirrer = Stirrer('COM4',9600)
    .....
 except:
    multimeter.close()
    amplifier.close()
    stirrer.close()

Но теперь проблема в блоке кода кроме ... Мы не уверены, что инициализация объектов прошла успешно и существуют ли они.Они могут не существовать, и поэтому мы не можем вызвать метод close ().

Поскольку создание экземпляров - это просто обычный последовательный код, я знаю, что при сбое создания экземпляра одного из моих классов все экземпляры других классов, предшествующих этой строке кода, выполняются успешно.Таким образом, вы можете попытаться создать экземпляр каждого класса и проверить, проваливается ли это или нет, и не удается ли закрыть соединения всех предыдущих объектов.

try:
   multimeter = Multimeter(192.168.1.5,5025)
except:
   #problem with the multimeter
   print('error')
try:
   amplifier = Amplifier(192.168.1.9,5025)
except:
   #problem with the amplifier, but we can close the multimeter
   multimeter.close()
try:
   stirrer = Stirrer('COM4',9600)
except: 
    #problem with the stirrer, but we can close the multimeter and the 
     amplifier
    multimeter.close()
    amplifier.close()
....

Но я думаю, что это ужасный код?В частности, когда количество объектов (в данном случае тестовых инструментов растет, это становится неуправляемым. И это чувствительно к ошибкам, когда вы хотите добавить или удалить объект ... Есть ли лучший способ убедиться, что все соединения закрыты? Сокеты должнызакрыть при ошибке, чтобы мы могли назначить ip-адрес и порт сокету при следующем запуске сценария. То же самое с последовательными интерфейсами, если он не закрыт, возникнет ошибка, поскольку вы не можете подключиться кпоследовательный интерфейс, который уже открыт ...

Ответы [ 2 ]

1 голос
/ 07 марта 2019

Используйте контейнер для хранения уже созданных инструментов и разделите ваш код на короткие, независимые, управляемые части:

def create_instruments(defs):
    instruments = {}
    for key, cls, params in instruments_defs:
        try:
            instruments[key] = cls(*params)
        except Exception as e:
            print("failed to instanciate '{}': {}".format(key, e))
            close_instruments(instruments)
            raise
    return instruments

def close_instruments(intruments):
    for key, instrument in intruments.items():
        try:
            instrument.close()
        except Exception as e:
            # just mention it - we can't do much more anyway
            print("got error {} when closing {}".format(e, key))


instruments_defs = [
    #(key, classname, (param1, ...)
    ("multimeter", Multimeter, ("192.168.1.5", 5025)),
    ("amplifier", Amplifier, ("192.168.1.9" ,5025)),
    ("stirrer", Stirrer, ('COM4',9600)),
    ]

instruments = create_instruments(instruments_defs)

Возможно, вы также захотите взглянуть на менеджеры контекста (главная причина работы менеджеров контекста - убедиться, что ресурсы высвобождаются должным образом), но это не обязательно лучший выбор (зависит от того, как вы используете эти объекты, как код структурирован и т. д.).

0 голосов
/ 07 марта 2019

На самом деле, решение, которое я предлагаю в моем вопросе, является самым простым способом решения этой проблемы. В блоке try скрипт пытается инициализировать экземпляры один за другим.

Если вы закроете объекты в том же порядке, в котором они были созданы в блоке try, то закрытие соединения будет успешным для каждого тестового инструмента, за исключением инструментов, которые не были инициализированы из-за ошибки, возникшей в попытке блок.

(см. Комментарии во фрагменте кода)

try:
    multimeter = Multimeter(192.168.1.5,5025) #succes
    amplifier = Amplifier(192.168.1.9,5025) #succes
    stirrer = Stirrer('COM4',9600) # error COM4 is not available --> jump to except
    generator = Generator()  #not initialized because of error in stirrer init
    otherTestInstrument = OtherTestInsrument() #not initialized because of error in stirrer init
    .....
 except:
    multimeter.close()  #initialized in try, so close() works
    amplifier.close()   #initialized in try, so close() works
    stirrer.close()     #probably initialized in try, so close() works probably
    generator.close()   #not initialized, will raise error, but doesn't matter.
    otherTestInstrument.close() #also not initialized. No need to close it too. 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...