1. Python / Говнокод #12089

    −106

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    >>> class Foo():
    ...     pass
    ... 
    >>> try:
    ...     raise Foo()
    ... except ExceptionBase as foo:
    ...     print 'foo %s' % foo
    ... except:
    ...     print 'not an exception'
    ... else:
    ...     print 'it\'s all good'
    ... 
    not an exception
    >>>

    Чет я как-то призадумался... Питон 2.7. Что делать-та?

    Запостил: wvxvw, 10 Ноября 2012

    Комментарии (68) RSS

    • Получается только как-то иззапазухи достать, через манипуляции со стеком и все такое. Что-то как-то вообще совсем не по-людски.
      Ответить
    • http://ideone.com/PA9zNx
      http://ideone.com/txAFim
      http://ideone.com/FryFoM
      http://ideone.com/vFTVWU
      В чем проблема?
      Ответить
      • /me ни разу не питонист
        class Foo:
            pass
         
        try:
            raise Foo()
        except Foo as foo:
            print "Foo"
        except:
            print "Oops!"
        else:
            print "Fail"


        http://ideone.com/uoFd29
        Ответить
        • И что? Неужели на столько не понятно в чем проблема? Нужно получить то, что бросили, а можно бросить не только ошибку, а никакой конструкции, чтобы получить любой объект / ошибку - нету, нужно только через стек и глубокую интроспекцию вылавливать.
          Ответить
          • В том же с++ тоже можно ловить всё подряд через catch(...), но и там нельзя получить доступ к объекту. Да и кидать всякую хуйню не порожденную от BaseException имхо моветон.

            > нужно только через стек и глубокую интроспекцию вылавливать
            Зачем? Есть же sys.exc_info().

            http://ideone.com/haVdKw
            Ответить
            • P.S. И кстати, что потом делать с пойманным объектом, у которого вы даже базовый класс не знаете (ведь если знали бы, написали бы его в except и рассматриваемой проблемы бы не возникло)?

              Разве что вызвать на нем str() и сохранить в лог...
              Ответить
            • Ну так наверное ж нельзя не потому, что в 2.Х все было так замечательно. Как бы С++ не показателен в смысле как нужно работать с исключениями. Примеров, где это плохо сделано может быть вообще даже больше, чем примеров, где это сделано хорошо.
              Ответить
              • Ну я все-таки считаю, что исключение это исключительная ситуация, поэтому бросаться должны потомки какого-либо специального класса, а не числа, строки, туплы, монетки, левые объекты и прочий мусор.

                Случай, когда нужно ловить объект неизвестно от чего порожденного класса очень подозрителен в плане архитектуры. Что потом можно с ним сделать кроме каста в строку или перевброса? Мы ведь ничего о нем не знаем, и поэтому практически ничего не можем с ним сделать.

                P.S. Для тех кому очень-очень нужно есть костыль sys.exc_info.
                Ответить
            • Моветон - это если самому такое делать, да и то не всегда, например, есть функция какого-нибудь толстого фреймворка, типа того же Джанго, где все уже вместо нас поймали, и нужно как-то из нее пробраться наверх, чтобы посигналить что выполнение дошло до какого-то места в коде. Не для рабочей версии, но для отладки - очень удобно.
              Еще вариант - демон скрипт, с закрытими дескрипторами инпут/аутпут, в котором важнее, чтобе стерпел, но продолжил работу, чем упал и даже сообщить не смог о том, что лучилось.
              Или еще вариант - сервер выполняющий программы написаные другими людьми, которые могут в принципе даже хотеть навредить, или навредить случайно.
              Вариантов использования можно придумать.
              И естесственно, нужно для логов, кроме str(), есть еще dict() которая может помочь разобраться в том, что это такое.
              Ответить
              • Ну собственно для всех этих применений вполне проканает описанный в документации костылёк с except без параметров и sys.exc_info внутри этой ветки. Эта конструкция действительно поймает всё.

                > чтобы посигналить что выполнение дошло до какого-то места в коде
                > для отладки - очень удобно
                А не будет ли проще записать сообщение в лог прямо на месте? Там и информации о проблеме побольше, и работу можно не прерывать.

                > сервер выполняющий программы написаные другими людьми
                > в котором важнее, чтобе стерпел, но продолжил работу,
                Вот поэтому мне и понравилось решение, принятое в третьем питоне. Все исключения порождены от BaseException, ничего другого вбросить нельзя. И написав except BaseException я буду уверен, что поймал все что могло прилететь.

                P.S. Сейчас внимательно посмотрел - даже 2.7 не дает кидать все подряд. Только old-style классы и new-style классы порожденные от BaseException.
                Ответить
                • > А не будет ли проще
                  Нет, не будет. Логи очень быстро переполняются и разбираться когда именно произошла какая запись - совсем не хочется. Или, еще вариант, выполнение кода приводит к бесконечному циклу - совсем не хочется в логе описывать бесконечный цикл.
                  Ответить
                  • Ну так помимо записи в лог можно и кинуть экцепшн, или вообще уронить программу, если это действительно фатально...

                    P.S. Какие-то притянутые за уши примеры у вас.
                    Ответить
                    • Если начать делать все, что можно сделать помимо основной задачи, можно сразу отказаться от написания программы на Питоне и писать на чем-то другом, а лучше просто сходить на море, или в магазин за пивом.
                      В чем смысл записать что-то в лог и тут же завершить программу, если это можно сделать одним действием?
                      Ответить
                      • > В чем смысл записать что-то в лог и тут же завершить программу, если это можно сделать одним действием?

                        Действительно. Зачем все эти пробросы исключений, если можно сделать все одним действием. sys.exit("shit happens"). В конце-концов выше вы пишете, что это для отладки, а не для продакшена.
                        Ответить
                        • Выше я пишу про разные возможные полезные применения.
                          Ответить
                          • Сорри, я сегодня сильно тупил. Все ок, понял вашу мысль про проброс исключений.
                            Ответить
                • Вот и выросло поколение программистов, не умеющее с лёгкостью разбирать четырёхгигабайтные логи...
                  На самом деле, <Личные данные удалены> (wvxvw) почти на 10 лет меня старше, но программировать я вроде начал раньше
                  Ответить
                  • >Олег (wvxvw)
                    <Личные_данные_удалены>?
                    Ответить
                    • Гы, решил в гугле посмотреть, что будет по wvxvw, нашел какую-то страничку любителя Мерлин Менсон... Но кавередж очень даже оказался неплохим. Нашел даже одну фотографию, которой у меня не было, на ней такое впечатление, что я женюсь на жене друга, а он нас поздравляет :/
                      Ответить
              • > и нужно как-то из нее пробраться наверх, чтобы посигналить что выполнение дошло до какого-то места в коде

                Всё-таки CL с его "гибкостью" и сигнальным протоколом необратимо травмирует мозг
                Ответить
                • Причем заметьте:
                  1) Первое требование wvxvw - вбросить исключение так, чтобы его не смогли поймать django и прочие.
                  2) Второе требование wvxvw - иметь такой обработчик, чтобы он ловил все исключения.

                  Странные, противоречащие друг другу требования...

                  Если бог сможет создать такой камень, что не сможет его поднять - он не всемогущ. Если бог не сможет создать такой камень, что не сможет его поднять - он не всемогущ. Вывод - бог не всемогущ.
                  Ответить
                  • Да нет никакого противоречия. Фреймворк использует конвенцию, что ловит только Exception, именно потому и для того, чтобы случайно не поймать чужие ошибки. Странно вообще, что эта концепция для кого-то новая, или непонятная. Такое впечатление, что все работают исключительно со своим кодом в котором ошибки случаются только по желанию авторов, и никогда - вопреки.
                    Ответить
                    • Пишу только вычислители факториалов, числодробилки и велосипеды.

                      В реальности ничего сложнее кривой змейки за всю жизнь не написал.
                      Ответить
                    • > Странно вообще, что эта концепция для кого-то новая, или непонятная.
                      С джанго не работал, его соглашений насчет исключений не знаю, поэтому ориентировался на ваше же высказывание:
                      >> где все уже вместо нас поймали

                      P.S. Способ как поймать все исключения был приведен выше. Давайте переводем тему в конструктивное русло или закроем ее.
                      Ответить
                      • Это не касается конкретно Джанго. Так поступают многие. Такая задача возникает часто.
                        Я не говорю, что решения нет вообще. Говнокод заключается в том, что решение плохое, а не в том, что оно отсутствует. Потому что система была построена непродумано. Т.е. человек, который запланировал ловить исключения, и по какой-то причине решил, что бросить Х можно, а ловить его наверное не нужно будет - сделал глупость. Я не знаю... если это не понятно, то мне остается только руками развести.
                        Ответить
                        • > Т.е. человек, который запланировал ловить исключения, и по какой-то причине решил, что бросить Х можно, а ловить его наверное не нужно будет - сделал глупость.

                          Ну вот по той же причине я и писал выше: "Вот поэтому мне и понравилось решение, принятое в третьем питоне. Все исключения порождены от BaseException, ничего другого вбросить нельзя. И написав except BaseException я буду уверен, что поймал все что могло прилететь.". Так что с этим я согласен.

                          Ну а то что решение для ловли всего подряд корявое - так и ООП в питоне 2.7 корявенькое. С двумя типами классов. Собственно только из-за этих old-style классов обработчик except BaseException и протекает...
                          Ответить
                  • бог может ложить на логику. При вопросе "может ли бог..." ответ всегда "да".
                    Ответить
                  • показать все, что скрытоvanished
                    Ответить
                • В CL можно и бряк поставить, для таких вещей это не нужно. Я с таким сталкивался во Флексе, там есть один часто используемый механизм, который отлавливает и "замалчивает" ошибки, врезультате чего, какой-нибудь безобидный код типа:
                  foo.bar = 42
                  может не сработать, а программа продолжит выполнятся дальше, и потом foo.bar не понятно чему равен и т.п. Но это с легкостью может произойти где угодно. Я напоролся на такое поведение в SCons, где вроде-бы безобидное except KeyError: поймало ошибку не из того словаря и просто проигнорировало. Потом очень долго искал, куда делась глобальная переменная. То она есть, а то ее нет, но программа притворяется как будто все замечательно.
                  Ответить
              • >>выполнение дошло до какого-то места в коде
                Может, модуль warnings поможет?
                Ответить
          • > а можно бросить не только ошибку
            У меня для вас плохие новости, в питоне 3 уже нельзя: http://ideone.com/btn9Xn.

            TypeError: exceptions must derive from BaseException
            TypeError: catching classes that do not inherit from BaseException is not allowed
            Ответить
            • В теме не просто так узказана версия. Питон 2.7 будет жить еще долго, изза того, что третий много чего сломал.
              Ответить
              • Тогда поясните пожалуйста, зачем кидать исключения не порожденные от BaseException?
                Ответить
                • А почему сразу такая уверенность, что я же должен и создавать исключение? Такое впечатление, что все и всегда работают исключительно со своим кодом, в котором они сами для себя решают, что вот этим они пользоваться не будут, а вот это никогда не случится и т. п.
                  Ситуация приведенная выше может случится даже неумышленно, если кто-то создавал ошибку не явно указывая глобальное имя, а опосредовано, через вызов функции, которая должна бы вернуть ошибку, а вернула что-то другое, или через обращение к переменной, в которой по ошибке оказалась не ошибка, а что-то другое. Нормальный, надежный код должен уметь вменяемо отреагировать на такие ситуации.
                  Ответить
                  • По-вашему так нормальный код должен нормально отреагировать на ситуацию когда компьютер развалило на части метеором. Есть определенные соглашения которые лучше не нарушать. Даже если надо.
                    Кидание черт знает чего вместо исключений - одно из них.
                    Ответить
                    • Да, потому что вы очевидно расстроитесь, когда это случится и напишете письмо в ЮНЕСКО о том как плохой другой программист вас обидел тем, что бросил ошибку, которую вы не ожидали - так что ли?
                      Ответить
                      • Потому что есть определенный предел до которого можно подстраиваться под чужой код. И хоть обычно и можно сделать из говна конфетку, но не всегда.

                        Можно, к примеру, убить вообще стандартный класс Exception, написав
                        del __builtins__.__dict__['Exception']

                        И это отработает. И что теперь, писать обертки и возвращать на место? Или все-таки выкинуть код который работает настолько через задницу, что усилия на его поддержку превысят усилия на его переделку.
                        Ответить
                        • У вас как с пониманием прочитанного? Написано же, код написан не мой. Попробуйте еще раз, с девятого слова.
                          Ответить
                          • Можно на "ты".
                            Какой именно код чужой?
                            Тот, который кидает всякую фигню? См. выше.
                            Тот, который ловит? Тогда вопрос чисто теоретический, потому что кидать невесть что - это плохая идея.
                            Ни тот ни другой? Тогда вообще не понимаю о чем разговор.
                            Ответить
                  • >А почему сразу такая уверенность, что я же должен и создавать исключение?
                    Потому, что исключения должны наследоваться от Exception. То, что другое выпилили из 3 кагбэ намекает.

                    Питон, в особенности двойка, позволяет делать много вещей, за которые надо бить по ебалу. В этом его проблема, да.
                    Ответить
      • Опечатался, когда копировал, BaseException, конечно.
        Остальные примеры - вообще не в кассу.
        Ответить
    • Наследоваться? Ловить то, что нужно? Или в чем вообще проблема?
      Ответить
    • Питонопроблемы
      Ответить
    • Гвидоклоуны.
      Ответить
    • Вероятно, надо унаследовать класс Foo от BaseException, например
      Ответить
    • Питон 2.7 прекратил поддержку. Не знал?
      Ответить

    Добавить комментарий