Очистка вложенных Try / Excepts

Я только что написал фрагмент кода, который поражает меня как гораздо более вложенного, чем оптимального. Я хотел бы посоветовать, как улучшить стиль этого, особенно, чтобы он больше соответствовал «Плоский лучше, чем вложенный».

for app in apps: if app.split('.', 1)[0] == 'zc': #only look for cron in zc apps try: a = app + '.cron' __import__(a) m = sys.modules[a] try: min = m.cron_minute() for job in min: k.add_interval_task(job[0], 'minute task', r(M_LB, M_UB), 60*job[1], kronos.method.threaded, (), ()) except AttributeError: #no minute tasks pass try: hour = m.cron_hour() for job in hour: k.add_daytime_task(job[0], 'day task', range(1, 8), None, (job[1], r(H_LB, H_UB)), kronos.method.threaded, (), ()) except AttributeError: #no hour tasks pass except ImportError: #no cron jobs for this module pass 

Изменить: Объединяя предложения ниже, вот моя переписанная форма.

 for app in apps: if app.split('.', 1)[0] != 'zc': #only look for cron in zc apps continue try: a = app + '.cron' __import__(a) except ImportError: #no cron jobs for this module, continue to next one continue m = sys.modules[a] if hasattr(m, 'cron_minute'): min = m.cron_minute() for job in min: k.add_interval_task(job[0], 'minute task', r(M_LB, M_UB), 60*job[1], kronos.method.threaded, (), ()) if hasattr(m, 'cron_hour'): hour = m.cron_hour() for job in hour: k.add_daytime_task(job[0], 'day task', range(1, 8), None, (job[1], r(H_LB, H_UB)), kronos.method.threaded, (), ()) 

4 Solutions collect form web for “Очистка вложенных Try / Excepts”

Основная проблема заключается в том, что ваши предложения try слишком широки, особенно самые отдаленные: с такой привычкой вы рано или поздно сталкиваетесь с загадочной ошибкой, потому что одна из ваших попыток / исключений случайно скрыла неожиданное исключение «пузыриться», от какой-либо другой функции, которую вы вызываете.

Поэтому я бы предложил, вместо этого:

 for app in apps: if app.split('.', 1)[0] != 'zc': #only look for cron in zc apps continue try: a = app + '.cron' __import__(a) except ImportError: #no cron jobs for this module continue # etc etc 

Как и в стороне, я также применяю «плоский лучше, чем вложенный» по-другому (не зависящий ни от какой try / except), что «если мне больше нечего делать на этой ноге цикла, продолжайте [т.е. двигайтесь дальше для следующего этапа цикла] вместо «если мне нужно что-то делать», за которым следует значительное количество вложенного кода. Я всегда предпочитал этот стиль (if / continue или if / return) для вложенных, если на языках такие функциональные возможности, как continue (по существу, все современные, поскольку C имеет это ;-).

Но это простой вариант «плоский против вложенного» стиля, и проблема в том, что вы не делаете свои предложения ! В худшем случае, когда вы просто не можете просто продолжить или вернуться в предложении except, вы можете использовать try / except / else: поместите в предложение try только то, что абсолютно ДОЛЖНО быть там – крошечный кусок кода, который, скорее всего, и ожидается raise – и добавьте остальную часть следующего кода (часть, которая НЕ допускается и не должна подниматься) в предложении else. Это не изменяет вложенность, но они делают огромную разницу в снижении риска случайного скрытия исключений, которые НЕ ожидаются!

Интересно, если рабочие места для каждой единицы времени фактически нарушаются, будут ли они поднимать AttibuteError или какое-либо другое исключение? В частности, если есть что-то о работе, которая действительно разрушена, вы, вероятно, не должны их поймать.

Другим вариантом, который может помочь, является обернуть только код нарушения с помощью try-catch, поставив обработчик исключений как можно ближе к исключению. Вот удар:

 for app in apps: if app.split('.', 1)[0] == 'zc': #only look for cron in zc apps try: a = app + '.cron' __import__(a) m = sys.modules[a] except ImportError: #no cron jobs for this module #exception is silently ignored #since no jobs is not an error continue if hasattr(m, "cron_minute"): min = m.cron_minute() for job in min: k.add_interval_task(job[0], 'minute task', r(M_LB, M_UB), 60*job[1], kronos.method.threaded, (), ()) if hasattr(m, "cron_hour"): hour = m.cron_hour() for job in hour: k.add_daytime_task(job[0], 'day task', range(1, 8), None, (job[1], r(H_LB, H_UB)), kronos.method.threaded, (), ()) 

Обратите внимание, что здесь есть только один обработчик исключений, с которым мы справляемся, правильно игнорируя. поскольку мы можем предсказать возможность того, что там не будет ни одного атрибута, мы проверяем его явно, что помогает сделать код более понятным. В противном случае, на самом деле не очевидно, почему вы ловите AttributeError или что даже поднимаете его.

Вы можете создать функцию, которая выполняет основную логику, и другую функцию, которая вызывает эту функцию, обертывая ее с помощью инструкций try … except. Затем в основном приложении вы можете просто вызвать те функции, которые уже обрабатывают исключения. (Исходя из рекомендаций книги «Чистый код»).

Ну, трюк здесь состоит в том, чтобы выяснить, нарушены ли они. Это часть обработки обработки исключений . Я имею в виду, по крайней мере, печатать предупреждение, в котором говорится о предположении комментария. Беспокойство по поводу чрезмерного гнездования до того, как фактическое обращение выглядит так, будто вы опережаете себя. Беспокойство о том, чтобы быть правым, прежде чем быть стильным.

  • Ошибка конечных точек приложения AppEngine Google: сбой настройки конфигурации службы (код состояния 404)
  • «pydoc -w EXPRESSIONS» не работает, но «pydoc EXPRESSIONS» делает. Зачем? (все заглавные разделы справки)
  • Как исправить TypeError: объект 'int' не является итерируемым?
  • Перемешивание нескольких итераций случайным образом при сохранении их порядка в python
  • Как «мин» двух целых чисел так же быстро, как «бит-хакинг»?
  • Непоследовательность синтаксиса Python?
  • ImportError: невозможно импортировать имя SignedJwtAssertionCredentials с помощью сервера AppEngine dev
  • Самый быстрый способ удалить все элементы вхождения из списка?
  • Python - лучший язык программирования в мире.