Несколько Try-Excepts с последующим Else в Python - PullRequest
4 голосов
/ 03 февраля 2010

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

Как пример:

 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 можно только в том случае, если все они погасли, однако, как написано в настоящее время, это зависит только от термометра нагревателя. Есть ли способ сложить их?

Ответы [ 5 ]

6 голосов
/ 03 февраля 2010

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

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')
6 голосов
/ 03 февраля 2010

Подумайте о том, чтобы разбить структуру 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')
6 голосов
/ 03 февраля 2010

Лично я бы просто имел переменную отключения init_ok или что-то подобное.

Установите его как True, и все условия исключения должны установить значение False, а затем проверить в конце?

3 голосов
/ 03 февраля 2010

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

2 голосов
/ 03 февраля 2010

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

Итак, я бы начал с ваших ..._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'], чтобы обратиться к определенному метру, или выполнить итерацию по счетчику, если вам нужно что-то сделать со всеми ними.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...