catching exceptions from an except: block

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Arnaud Delobelle

    #1

    catching exceptions from an except: block

    Hi all,

    Imagine I have three functions a(x), b(x), c(x) that each return
    something or raise an exception. Imagine I want to define a function
    that returns a(x) if possible, otherwise b(x), otherwise c(x),
    otherwise raise CantDoIt.

    Here are three ways I can think of doing it:

    ----------
    # This one looks ugly
    def nested_first(x) :
    try:
    return a(x)
    except:
    try:
    return b(x)
    except:
    try:
    return c(x)
    except:
    raise CantDoIt

    # This one looks long-winded
    def flat_first(x):
    try:
    return a(x)
    except:
    pass
    try:
    return b(x)
    except:
    pass
    try:
    return c(x)
    except:
    raise CantDoIt

    # This one only works because a,b,c are functions
    # Moreover it seems like an abuse of a loop construct to me
    def rolled_first(x) :
    for f in a, b, c:
    try:
    return f(x)
    except:
    continue
    raise CantDoIt
    ----------

    I don't feel happy with any of these. Is there a more satisfying way
    of doing this in Python? What I would like is something like:

    ----------
    # This one isn't correct but looks the clearest to me
    def wished_first(x) :
    try:
    return a(x)
    except:
    return b(x)
    except:
    return c(x)
    except:
    raise CantDoIt
    ----------

    I guess what I'm looking for is some sort of
    if:
    elif:
    ....
    elif:
    else:

    but for try: except:
    That's why
    try:
    except:
    except:
    ....
    except:

    seemed natural to me :) And I'd like to find a nice way to do this in
    a syntactically correct way.

    Note: I've chosen functions a, b, c, but really I'm looking for a way
    that is suitable for any chunk of code.

  • Miki

    #2
    Re: catching exceptions from an except: block

    Hello Arnaud,
    Imagine I have three functions a(x), b(x), c(x) that each return
    something or raise an exception. Imagine I want to define a function
    that returns a(x) if possible, otherwise b(x), otherwise c(x),
    otherwise raise CantDoIt.
    Exceptions are for error handling, not flow control.
    Here are three ways I can think of doing it:
    ...
    # This one only works because a,b,c are functions
    # Moreover it seems like an abuse of a loop construct to me
    def rolled_first(x) :
    for f in a, b, c:
    try:
    return f(x)
    except:
    continue
    raise CantDoIt
    My vote is for that one.
    I don't feel happy with any of these. Is there a more satisfying way
    of doing this in Python? What I would like is something like:
    >
    ----------
    # This one isn't correct but looks the clearest to me
    def wished_first(x) :
    try:
    return a(x)
    except:
    return b(x)
    except:
    return c(x)
    except:
    raise CantDoIt
    Again, exception are for error handling, not for flow control.

    As a side note, try to avoid "catch:", always catch explicit
    exceptions.

    HTH,
    Miki <miki.tebeka@gm ail.com>
    If it won't be simple, it simply won't be. [Hire me, source code]


    Comment

    • Arnaud Delobelle

      #3
      Re: catching exceptions from an except: block

      On 7 Mar, 19:26, "Miki" <miki.teb...@gm ail.comwrote:
      Hello Arnaud,
      Hi Miki

      [snip]
      Exceptions are for error handling, not flow control.
      Maybe but it's not always that clear cut! As error handling is a form
      of flow control the two have to meet somewhere.

      [snip]
      As a side note, try to avoid "catch:", always catch explicit
      exceptions.
      I didn't specify what I wanted to catch because it didn't feel it was
      relevant to the problem.

      Thanks

      --
      Arnaud

      Comment

      • Marc 'BlackJack' Rintsch

        #4
        Re: catching exceptions from an except: block

        In <1173292373.770 519.158490@8g20 00cwh.googlegro ups.com>, Arnaud Delobelle
        wrote:
        # This one only works because a,b,c are functions
        # Moreover it seems like an abuse of a loop construct to me
        def rolled_first(x) :
        for f in a, b, c:
        try:
        return f(x)
        except:
        continue
        raise CantDoIt
        ----------
        Why do you think this is an abuse? I think it's a perfectly valid use of
        a loop.

        Ciao,
        Marc 'BlackJack' Rintsch

        Comment

        • Marc 'BlackJack' Rintsch

          #5
          Re: catching exceptions from an except: block

          In <1173295587.143 018.102220@p10g 2000cwp.googleg roups.com>, Miki wrote:
          Exceptions are for error handling, not flow control.
          That's not true, they are *exceptions* not *errors*. They are meant to
          signal exceptional situations. And at least under the cover it's used in
          every ``for``-loop because the end condition is signaled by a
          `StopIteration` exception. Looks like flow control to me.

          Ciao,
          Marc 'BlackJack' Rintsch

          Comment

          • Larry Bates

            #6
            Re: catching exceptions from an except: block

            Arnaud Delobelle wrote:
            Hi all,
            >
            Imagine I have three functions a(x), b(x), c(x) that each return
            something or raise an exception. Imagine I want to define a function
            that returns a(x) if possible, otherwise b(x), otherwise c(x),
            otherwise raise CantDoIt.
            >
            Here are three ways I can think of doing it:
            >
            ----------
            # This one looks ugly
            def nested_first(x) :
            try:
            return a(x)
            except:
            try:
            return b(x)
            except:
            try:
            return c(x)
            except:
            raise CantDoIt
            >
            # This one looks long-winded
            def flat_first(x):
            try:
            return a(x)
            except:
            pass
            try:
            return b(x)
            except:
            pass
            try:
            return c(x)
            except:
            raise CantDoIt
            >
            # This one only works because a,b,c are functions
            # Moreover it seems like an abuse of a loop construct to me
            def rolled_first(x) :
            for f in a, b, c:
            try:
            return f(x)
            except:
            continue
            raise CantDoIt
            ----------
            >
            I don't feel happy with any of these. Is there a more satisfying way
            of doing this in Python? What I would like is something like:
            >
            ----------
            # This one isn't correct but looks the clearest to me
            def wished_first(x) :
            try:
            return a(x)
            except:
            return b(x)
            except:
            return c(x)
            except:
            raise CantDoIt
            ----------
            >
            I guess what I'm looking for is some sort of
            if:
            elif:
            ...
            elif:
            else:
            >
            but for try: except:
            That's why
            try:
            except:
            except:
            ...
            except:
            >
            seemed natural to me :) And I'd like to find a nice way to do this in
            a syntactically correct way.
            >
            Note: I've chosen functions a, b, c, but really I'm looking for a way
            that is suitable for any chunk of code.
            >
            Without knowing more about the functions and the variable it is somewhat
            hard to tell what you are trying to accomplish. If a, b, c are functions
            that act on x when it is a different type, change to one function that
            can handle all types.

            def d(x):
            if isinstance(x, basestring):
            #
            # Code here for string
            #
            elif isinstance(x, int):
            #
            # Code here for int
            #
            elif isinstance(x, float):
            #
            # Code here for string
            #
            else:
            raise ValueError


            If they are different functions based on type do something like this:

            #
            # Set up a dictionary with keys for different types and functions
            # that correspond.
            #
            fdict={type('') : a, type(1): b, type(1.0): c}
            #
            # Call the appropriate function based on type
            #
            fdict[type(x)](x)

            -Larry

            Comment

            • Bruno Desthuilliers

              #7
              Re: catching exceptions from an except: block

              Miki a écrit :
              Hello Arnaud,
              >
              >
              >>Imagine I have three functions a(x), b(x), c(x) that each return
              >>something or raise an exception. Imagine I want to define a function
              >>that returns a(x) if possible, otherwise b(x), otherwise c(x),
              >>otherwise raise CantDoIt.
              >
              Exceptions are for error handling, not flow control.
              def until(iterable, sentinel):
              for item in iterable:
              if item == sentinel:
              raise StopIteration
              yield item
              >>for item in until(range(10) , 5):
              .... print item
              ....
              0
              1
              2
              3
              4
              >>>
              Exceptions *are* a form of flow control.

              Comment

              • Bruno Desthuilliers

                #8
                Re: catching exceptions from an except: block

                Larry Bates a écrit :
                (snip)
                def d(x):
                if isinstance(x, basestring):
                #
                # Code here for string
                #
                elif isinstance(x, int):
                #
                # Code here for int
                #
                elif isinstance(x, float):
                #
                # Code here for string
                #
                else:
                raise ValueError
                As a side note : While there are a few corner cases where this is hardly
                avoidable (and yet I'd rather test on interface, not on concrete type),
                this kind of cose is exactly what OO polymorphic dispatch is supposed to
                avoid (no, don't tell me: I know you can't easily add methods to most
                builtin types).

                Comment

                • Gabriel Genellina

                  #9
                  Re: catching exceptions from an except: block

                  En Wed, 07 Mar 2007 19:00:59 -0300, Bruno Desthuilliers
                  <bdesth.quelque chose@free.quel quepart.frescri bió:
                  this kind of cose is exactly what OO polymorphic dispatch is supposed to
                  this kind of cose? Ce genre de chose?

                  --
                  Gabriel Genellina

                  Comment

                  • Arnaud Delobelle

                    #10
                    Re: catching exceptions from an except: block

                    On Mar 7, 8:52 pm, Larry Bates <lba...@websafe .comwrote:
                    [snip]
                    Without knowing more about the functions and the variable it is somewhat
                    hard to tell what you are trying to accomplish. If a, b, c are functions
                    that act on x when it is a different type, change to one function that
                    can handle all types.
                    I'm not really thinking about this situation so let me clarify. Here
                    is a simple concrete example, taking the following for the functions
                    a,b,c I mention in my original post.
                    - a=int
                    - b=float
                    - c=complex
                    - x is a string
                    This means I want to convert x to an int if possible, otherwise a
                    float, otherwise a complex, otherwise raise CantDoIt.

                    I can do:

                    for f in int, float, complex:
                    try:
                    return f(x)
                    except ValueError:
                    continue
                    raise CantDoIt

                    But if the three things I want to do are not callable objects but
                    chunks of code this method is awkward because you have to create
                    functions simply in order to be able to loop over them (this is whay I
                    was talking about 'abusing loop constructs'). Besides I am not happy
                    with the other two idioms I can think of.

                    --
                    Arnaud

                    Comment

                    • Bruno Desthuilliers

                      #11
                      Re: catching exceptions from an except: block

                      Arnaud Delobelle a écrit :
                      Hi all,
                      >
                      Imagine I have three functions a(x), b(x), c(x) that each return
                      something or raise an exception. Imagine I want to define a function
                      that returns a(x) if possible, otherwise b(x), otherwise c(x),
                      otherwise raise CantDoIt.
                      >
                      Here are three ways I can think of doing it:
                      >
                      ----------
                      # This one looks ugly
                      Yes.
                      def nested_first(x) :
                      try:
                      return a(x)
                      except:
                      <side-note>
                      Try avoiding bare except clauses. It's usually way better to specify the
                      type(s) of exception you're expecting to catch, and let other propagate.
                      </side-note>
                      try:
                      return b(x)
                      except:
                      try:
                      return c(x)
                      except:
                      raise CantDoIt
                      >
                      # This one looks long-winded
                      Yes. And not's very generic.
                      def flat_first(x):
                      try:
                      return a(x)
                      except:
                      pass
                      try:
                      return b(x)
                      except:
                      pass
                      try:
                      return c(x)
                      except:
                      raise CantDoIt
                      >
                      # This one only works because a,b,c are functions
                      It works with any callable. Anyway, what else would you use here ???
                      # Moreover it seems like an abuse of a loop construct to me
                      Why so ? loops are made for looping, adn functions are objects like any
                      other.
                      def rolled_first(x) :
                      for f in a, b, c:
                      try:
                      return f(x)
                      except:
                      continue
                      raise CantDoIt
                      Here's an attempt at making it a bit more generic (<side-note>it still
                      lacks a way to specify which kind of exceptions should be silently
                      swallowed</side-note>.

                      def trythese(*funct ions):
                      def try_(*args, **kw):
                      for func in functions:
                      try:
                      return func(*args, **kw)
                      except: # FIX ME : bare except clause
                      pass
                      else:
                      # really can't do it, sorry
                      raise CantDoIt
                      return try_

                      result = trythese(a, b, c)(x)
                      ----------
                      # This one isn't correct but looks the clearest to me
                      def wished_first(x) :
                      try:
                      return a(x)
                      except:
                      return b(x)
                      except:
                      return c(x)
                      except:
                      raise CantDoIt
                      Having multiple except clauses is correct - but it has another semantic.

                      Note: I've chosen functions a, b, c, but really I'm looking for a way
                      that is suitable for any chunk of code.
                      A function is an object wrapping a chunk of code...

                      I personnaly find the loop-based approach quite clean and pythonic.

                      Comment

                      • garrickp@gmail.com

                        #12
                        Re: catching exceptions from an except: block

                        On Mar 7, 2:48 pm, "Arnaud Delobelle" <arno...@google mail.comwrote:
                        >
                        I'm not really thinking about this situation so let me clarify. Here
                        is a simple concrete example, taking the following for the functions
                        a,b,c I mention in my original post.
                        - a=int
                        - b=float
                        - c=complex
                        - x is a string
                        This means I want to convert x to an int if possible, otherwise a
                        float, otherwise a complex, otherwise raise CantDoIt.
                        >
                        I can do:
                        >
                        for f in int, float, complex:
                        try:
                        return f(x)
                        except ValueError:
                        continue
                        raise CantDoIt
                        >
                        But if the three things I want to do are not callable objects but
                        chunks of code this method is awkward because you have to create
                        functions simply in order to be able to loop over them (this is whay I
                        was talking about 'abusing loop constructs'). Besides I am not happy
                        with the other two idioms I can think of.
                        >
                        --
                        Arnaud
                        Wouldn't it be easier to do:

                        if isinstance(x, int):
                        # do something
                        elif isinstance(x, float)t:
                        # do something
                        elif isinstance(x, complex):
                        # do something
                        else:
                        raise CantDoIt

                        or,

                        i = [int, float, complex]
                        for f in i:
                        if isinstance(x, f):
                        return x
                        else:
                        raise CantDoIt

                        Comment

                        • Bruno Desthuilliers

                          #13
                          Re: catching exceptions from an except: block

                          Gabriel Genellina a écrit :
                          En Wed, 07 Mar 2007 19:00:59 -0300, Bruno Desthuilliers
                          <bdesth.quelque chose@free.quel quepart.frescri bió:
                          >
                          >this kind of cose is exactly what OO polymorphic dispatch is supposed to
                          >
                          >
                          this kind of cose?
                          sorry
                          s/cose/code/
                          Ce genre de chose?
                          >
                          En quelques sortes, oui, quoique pas tout à fait !-)

                          Comment

                          • garrickp@gmail.com

                            #14
                            Re: catching exceptions from an except: block

                            On Mar 7, 3:04 pm, garri...@gmail. com wrote:
                            On Mar 7, 2:48 pm, "Arnaud Delobelle" <arno...@google mail.comwrote:
                            >
                            >
                            >
                            >
                            >
                            I'm not really thinking about this situation so let me clarify. Here
                            is a simple concrete example, taking the following for the functions
                            a,b,c I mention in my original post.
                            - a=int
                            - b=float
                            - c=complex
                            - x is a string
                            This means I want to convert x to an int if possible, otherwise a
                            float, otherwise a complex, otherwise raise CantDoIt.
                            >
                            I can do:
                            >
                            for f in int, float, complex:
                            try:
                            return f(x)
                            except ValueError:
                            continue
                            raise CantDoIt
                            >
                            But if the three things I want to do are not callable objects but
                            chunks of code this method is awkward because you have to create
                            functions simply in order to be able to loop over them (this is whay I
                            was talking about 'abusing loop constructs'). Besides I am not happy
                            with the other two idioms I can think of.
                            >
                            --
                            Arnaud
                            >
                            Wouldn't it be easier to do:
                            >
                            if isinstance(x, int):
                            # do something
                            elif isinstance(x, float)t:
                            # do something
                            elif isinstance(x, complex):
                            # do something
                            else:
                            raise CantDoIt
                            >
                            or,
                            >
                            i = [int, float, complex]
                            for f in i:
                            if isinstance(x, f):
                            return x
                            else:
                            raise CantDoIt
                            I so missed the point of this. Not my day. Please ignore my post.

                            Comment

                            • Gabriel Genellina

                              #15
                              Re: catching exceptions from an except: block

                              En Wed, 07 Mar 2007 18:48:18 -0300, Arnaud Delobelle
                              <arnodel@google mail.comescribi ó:
                              for f in int, float, complex:
                              try:
                              return f(x)
                              except ValueError:
                              continue
                              raise CantDoIt
                              >
                              But if the three things I want to do are not callable objects but
                              chunks of code this method is awkward because you have to create
                              functions simply in order to be able to loop over them (this is whay I
                              was talking about 'abusing loop constructs'). Besides I am not happy
                              with the other two idioms I can think of.
                              Hmmm, functions are cheap - nobody is charging you $2 for each "def"
                              statement you write, I presume :)

                              A bit more serious, if those "chunks of code" are processing its input and
                              returning something that you further process... they *are* functions. If
                              you don't want them to be publicly available, use inner functions:

                              def xxxfactory(x):
                              def f1(x):
                              ...
                              def f2(x):
                              ...
                              def f3(x):
                              ...

                              for f in f1,f2,f3:
                              try:
                              return f(x)
                              ... same as above...

                              --
                              Gabriel Genellina

                              Comment

                              Working...