2010-02-03 2 views
4

Есть ли способ иметь несколько последовательных предложений Try-Except, которые запускают один Else, только если все они успешны?Несколько Try-Excepts, за которыми следует Else в python

В качестве примера:

try: 
    private.anodization_voltage_meter = Voltmeter(voltage_meter_address.value) #assign voltmeter location 
except(visa.VisaIOError): #channel time out 
    private.logger.warning('Volt Meter is not on or not on this channel') 
try: 
    private.anodization_current_meter = Voltmeter(current_meter_address.value) #assign voltmeter as current meter location 
except(visa.VisaIOError): #channel time out 
    private.logger.warning('Ammeter is not on or not on this channel') 
try: 
    private.sample_thermometer = Voltmeter(sample_thermometer_address.value)#assign voltmeter as thermomter location for sample. 
except(visa.VisaIOError): #channel time out 
    private.logger.warning('Sample Thermometer is not on or not on this channel') 
try: 
    private.heater_thermometer = Voltmeter(heater_thermometer_address.value)#assign voltmeter as thermomter location for heater. 
except(visa.VisaIOError): #channel time out 
    private.logger.warning('Heater Thermometer is not on or not on this channel') 
else: 
    private.logger.info('Meters initialized') 

Как вы можете видеть, вы только хотите напечатать meters initialized если все они ушли, однако в настоящее время написано, это зависит только от термометра нагревателя. есть ли способ их уложить?

+4

Если вы пишете много блоков исключений, вы, вероятно, используете исключения. Исключения не являются условными. –

+1

Судя по сообщениям об ошибках, они выглядят как допустимые исключения для меня. – Steve314

+0

Исключения не достаточно гранулированы. Вольтметр только генерирует общий «VISAIOError» независимо от проблем, с которыми он сталкивается. Этот вопрос/проблема не возникнет, если вместо этого Вольтметр бросил конкретное исключение для каждой проблемы. –

ответ

3

Вы можете оставить булево, инициализирован в начале, чтобы: everythingOK=True Затем установите его в False во всех, за исключением блоков и войти только если это правда в последней строке.

6

Рассмотрите возможность разбиения структуры try/except на функцию, которая возвращает True, если вызов работал, и False, если это не удалось, затем используйте, например, all() видеть, что все они преуспели:

def initfunc(structure, attrname, address, desc): 
    try: 
    var = Voltmeter(address.value) 
    setattr(structure, attrname, var) 
    return True 
    except(visa.VisaIOError): 
    structure.logger.warning('%s is not on or not on this channel' % (desc,)) 

if all([initfunc(*x) for x in [(private, 'anodization_voltage_meter', voltage_meter_address, 'Volt Meter'), ...]]): 
    private.logger.info('Meters initialized') 
+1

Это будет короткое замыкание при первом вызове, который терпит неудачу, что по-разному относится к оригиналу. –

+0

Хороший звонок. Исправлена. –

6

Лично я бы просто поездка переменной init_ok или сконвертировано.

Установите его как «Истина», и у него есть все исключения, кроме него, False, а затем тест в конце?

+0

Простой, чистый, элегантный. Мне это нравится. – Jerub

+0

'import this' довольно много подводит итог философии. – richo

6

Попробуйте что-нибудь подобное. сохраняя оригинальное поведение не останавливается после первого исключения

success = True 
for meter, address, message in (
     ('anodization_voltage_meter',voltage_meter_address,'Volt Meter is not on or not on this channel'), 
     ('anodization_current_meter',current_meter_address,'Ammeter is not on or not on this channel'), 
     ('sample_thermometer',sample_thermometer_address,'Sample Thermometer is not on or not on this channel'), 
     ('heater_thermometer',heater_thermometer_address,'Heater Thermometer is not on or not on this channel')): 
    try: 
     setattr(private,meter, Voltmeter(address.value): 
    except (visa.VisaIOError,): 
     success = False 
     private.logger.warning(message) 

if success: # everything is ok 
    private.logger.info('Meters initialized') 
+0

+1 - абсолютно путь! Этот 3-кортеж на самом деле выглядит так, как будто он может стать классом или, по крайней мере, именованным, поскольку я подозреваю, что может быть дальнейшее поведение или данные, которые будут связаны с этими метрами. – PaulMcG

2

У вас есть ряд весьма схожих объекты, а также в тех случаях, как это часто бывает лучше относиться к ним равномерно и использовать подход управляемых данных.

Итак, я бы начал с ваших ..._meter_address объектов. Для меня они звучат как конфигурации для счетчиков, поэтому я есть класс, который выглядит примерно так:

class MeterConfiguration(object): 
    def __init__(self, name, address): 
     self.name = name 
     self.address = address 

    def english_name(self): 
     """A readable form of the name for this meter.""" 
     return ' '.join(x.title() for x in self.name.split('_')) + ' Meter' 

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

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

ALL_METERS = [ 
    MeterConfiguration('anodization_voltage', 'PORT0001'), 
    MeterConfiguration('anodization_current', 'PORT0002'), 
    MeterConfiguration('sample_thermometer', 'PORT0003'), 
    MeterConfiguration('heater_thermometer', 'PORT0004') 
] 

Круто, теперь все настройки в одном месте, и мы можем использовать это, чтобы сделать вещи проще и равномерными.

private.meters = {} 
any_errors = False 
for meter in ALL_METERS: 
    try: 
     private.meters[meter.name] = Voltmeter(meter.address) 
    except VisaError: 
     logging.error('%s not found at %s', meter.english_name(), meter.address) 
     any_errors = True 
if not any_errors: 
    logging.info('All meters initialized.') 

Вы можете использовать, например private.meters['anodization_voltage'] для обозначения конкретного прибора, или перебирать метров ДИКТ, если вам нужно сделать что-то для всех.