WedX - журнал о программировании и компьютерных науках

Выбросить исключение, не останавливая выполнение?

Я залез в дыру в проекте, над которым работаю. У меня есть этот массивный проект (сотни тысяч строк), и везде есть ошибки MySQL. Я сейчас занимаюсь их очисткой.

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

Я надеялся, что set_exception_handler сделает то, что я хочу, но в документах конкретно сказано, что он остановит выполнение после вызова моего обработчика. Итак, как мне обойти это?

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


Чтобы уточнить:

Я хочу создать исключение из моего класса базы данных (всякий раз, когда возникает ошибка SQL). Затем я хочу зарегистрировать эту ошибку и/или отобразить сообщение на экране до тех пор, пока я не смогу либо исправить ошибку SQL, либо обернуть ошибочную строку в try/catch. Я не хочу, чтобы это останавливало выполнение. Если я просто вызову какую-нибудь функцию error_handler() вместо того, чтобы генерировать исключение, то я не смогу ее перехватить. Если я поймаю его немедленно (также в классе DB), то я не смогу поймать его дальше по стеку (если я не выкину его повторно, но тогда мы вернемся к остановке выполнения).


  • Если вы уже обновили код для преобразования ошибок MySQL в исключения, почему бы просто не зарегистрировать ошибку вместо создания исключения? 29.02.2012
  • @pgraham: Черт возьми ... это хороший вопрос. Причина в том, что я хотел иметь возможность поймать исключение, если я не хочу, чтобы оно попадало в глобальный обработчик исключений. Кроме того, мне нужна централизованная функция обработки исключений и ведения журнала. Наконец, после того, как я устраню ошибки, я хочу немного изменить глобальный обработчик исключений, чтобы он фактически действительно умирал и выдавал фатальную ошибку. 29.02.2012
  • @downvoter: Не хочешь объяснить, почему это плохой вопрос? 29.02.2012
  • Я не хочу показаться неприятным или что-то в этом роде, но похоже, что вы не знакомы с тем, как работают исключения (удаление кадров из стека, потеря текущих значений переменных env и т. д.). Что вы хотите сделать, так это просто добавить отладочную печать, как прокомментировал здесь @pgraham, и как я прокомментировал ответ, который вы опубликовали и удалили. Я думаю, что ваш вопрос больше запутает, чем поможет другим людям. Поэтому я решил понизить голос. 29.02.2012
  • @alfasin: 1) Я удалил свой пост, потому что понял, что он не имеет смысла после того, как Пгрэм задал вопрос выше, 2) Сам вопрос не предназначен для того, чтобы кого-то просветить, поэтому это вопрос. Если вы считаете, что это плохая идея, опубликуйте почему в качестве ответа, чтобы он мог им помочь. Голосование против вопроса из-за ошибочных убеждений может помешать другим людям с таким же неправильным мышлением учиться. 3) У меня была отладочная печать. Мне нужны исключения, чтобы их можно было поймать (как объяснено в комментарии выше). 01.03.2012
  • Кроме того, они должны быть исключениями. Ошибка SQL — это ошибка, мой проект просто не в том состоянии, когда взрыв допустим. Я пытаюсь пойти на компромисс, создав временную паузу, пока не закончу исправлять ошибки. 01.03.2012
  • Короткий ответ - нет. Если вы не можете обернуть весь код в блоки try/catch, то все, что достигает обработчика исключений верхнего уровня, умрет. Я бы порекомендовал определить функцию ведения журнала, в которую вы можете передать исключение. Затем вместо того, чтобы генерировать исключение при преобразовании ошибок MySQL в исключения, передайте его функции регистрации. Позже, когда вам понадобится фатальная ошибка, вам нужно будет только обновить функцию ведения журнала, чтобы она также выдавала исключение. 01.03.2012
  • @pgraham: Да, это именно то, что я делал какое-то время, но это казалось довольно хакерским, поэтому я начал использовать trigger_error вместо E_USER_WARNING, а затем, если я хочу повысить серьезность, я могу изменить его на E_USER_ERROR. Хотя более-менее такой же результат. Спасибо. 02.03.2012

Ответы:


1

Если я вас правильно понял:

function myFunction($params) {

    try {

        //your code which throws Exception

    } catch (Exception $e) {

        myErrorFunction($e);
        return false;
    }

}
29.02.2012
  • Нет, я не думаю, что вы понимаете все мои требования. Куда бы я поместил попытку/поймать? У меня сейчас нет времени, чтобы помещать его в каждый отдельный SQL-запрос, поэтому мне пришлось бы размещать его именно там, где я его бросаю... но тогда я не могу поймать его дальше, потому что я его уже поймал. . Я не думаю, что то, что я хочу сделать, возможно. 01.03.2012
  • Вы можете обернуть весь код или просто использовать его в своем классе базы данных. Сколько у вас методов? 10? 20? Просто оберните их с помощью try catch, и каждый раз, когда вы выполняете его, например $db->myCustonQuery(), вы знаете, что если произойдет ошибка, он вызовет исключение, которое вы можете обработать где-то еще. Суть этого ответа в том, что если вы return false, вы сможете продолжить выполнение. 01.03.2012
  • Если я оберну весь код, то при возникновении исключения выполнение упадет до этой точки (улов); Мне нужно, чтобы он продолжался с того места, где он остановился (в броске). Сколько методов? Что, в моем классе БД? 10-20 — разумная оценка, но их обертывание также не позволяет мне поймать его там, где я хочу. В основном я хочу иметь возможность поймать, где я вызываю $db->GetSingleRecord(), но необязательно, потому что есть тысячи вызовов указанной функции, и мне нужно пройти их все. Имеет ли это смысл? Я думаю, что то, что я прошу, нереально, но это было бы оптимальным случаем. 01.03.2012
  • Помимо временных ограничений, похоже, что вам действительно нужно реорганизовать все это. 01.03.2012
  • @Ing: Я бы с удовольствием. К сожалению, временные ограничения — это реальная вещь, которую нельзя игнорировать. 01.03.2012

  • 2

    Я думаю, что нашел обходной путь. Вместо того, чтобы сгенерировать исключение, я могу вызвать свой обработчик напрямую с исключением:

    global_exception_handler(new MySqlException($error_message)); 
    

    Таким образом, мой обработчик все еще вызывается, но выполнение продолжается.

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

    function _global_exception_handler($e) {
        // log error here
    }
    
    set_exception_handler('global_exception_handler');
    
    29.02.2012
  • это похоже на добавление отладочной печати, нет? 29.02.2012

  • 3

    Старый пост, который я знаю, но я тоже задал этот вопрос и узнал, что ответ состоял в том, чтобы добавить эту строку вверху, где вы используете try catch (Exception):

    использовать Исключение;

    14.07.2021
    Новые материалы

    Объяснение документов 02: BERT
    BERT представил двухступенчатую структуру обучения: предварительное обучение и тонкая настройка. Во время предварительного обучения модель обучается на неразмеченных данных с помощью..

    Как проанализировать работу вашего классификатора?
    Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

    Работа с цепями Маркова, часть 4 (Машинное обучение)
    Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

    Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
    Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..

    Использование машинного обучения и Python для классификации 1000 сезонов новичков MLB Hitter
    Чему может научиться машина, глядя на сезоны новичков 1000 игроков MLB? Это то, что исследует это приложение. В этом процессе мы будем использовать неконтролируемое обучение, чтобы..

    Учебные заметки: создание моего первого пакета Node.js
    Это мои обучающие заметки, когда я научился создавать свой самый первый пакет Node.js, распространяемый через npm. Оглавление Глоссарий I. Новый пакет 1.1 советы по инициализации..

    Забудьте о Matplotlib: улучшите визуализацию данных с помощью умопомрачительных функций Seaborn!
    Примечание. Эта запись в блоге предполагает базовое знакомство с Python и концепциями анализа данных. Привет, энтузиасты данных! Добро пожаловать в мой блог, где я расскажу о невероятных..


    Для любых предложений по сайту: [email protected]