Identifying exceptions that can be raised

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

    Identifying exceptions that can be raised

    I'm very new to Python, but I couldn't find anything in the docs or faq
    about this. And I fished around in the IDLE menus but didn't see anything.

    Is there a tool that can determine all the exceptions that can be raised
    in a Python function, or in any of the functions it calls, etc.?

    /Dan
  • Brian van den Broek

    #2
    Re: Identifying exceptions that can be raised

    dkcpub said unto the world upon 2004-11-18 22:38:[color=blue]
    > I'm very new to Python, but I couldn't find anything in the docs or faq
    > about this. And I fished around in the IDLE menus but didn't see anything.
    >
    > Is there a tool that can determine all the exceptions that can be raised
    > in a Python function, or in any of the functions it calls, etc.?
    >
    > /Dan[/color]

    Hi Dan,

    Do you mean all the exceptions that exist? If so, while I don't know
    Python well enough to vouch for its completeness, check out
    <http://www.python.org/doc/2.3.4/lib/module-exceptions.html >.

    If you mean you want a list of exceptions that a given function could
    raise, well, never mind :-)

    Best,

    Brian vdB

    Comment

    • dkcpub

      #3
      Re: Identifying exceptions that can be raised

      Brian van den Broek wrote:[color=blue]
      > If you mean you want a list of exceptions that a given function could
      > raise, well, never mind :-)[/color]

      Yeah, that is what I mean. I write foo(), which calls a half-dozen
      library functions. What exceptions is a caller of foo() going to have
      to handle? It there an automated way of discovering that?

      /Dan

      Comment

      • Peter Otten

        #4
        Re: Identifying exceptions that can be raised

        dkcpub wrote:
        [color=blue]
        > Brian van den Broek wrote:[color=green]
        >> If you mean you want a list of exceptions that a given function could
        >> raise, well, never mind :-)[/color]
        >
        > Yeah, that is what I mean. I write foo(), which calls a half-dozen
        > library functions. What exceptions is a caller of foo() going to have
        > to handle? It there an automated way of discovering that?
        >
        > /Dan[/color]

        None that I know of. You just have to feed the function the typical data and
        any corner cases that you can think of and handle all failures that appear
        in the process. The unittest module can help you automate this.
        Hoping to ever get a comprehensive set of exceptions a function can raise is
        a vain effort in Python. A little example may illustrate this:
        [color=blue][color=green][color=darkred]
        >>> def add(a, b):[/color][/color][/color]
        .... return a + b
        ....[color=blue][color=green][color=darkred]
        >>> add(1, 2)[/color][/color][/color]
        3[color=blue][color=green][color=darkred]
        >>> add(1, "2")[/color][/color][/color]
        Traceback (most recent call last):
        File "<stdin>", line 1, in ?
        File "<stdin>", line 2, in add
        TypeError: unsupported operand type(s) for +: 'int' and 'str'

        The above calls should cover the typical usage of our trivial function. Does
        it make sense then, to document/report that add() may raise a TypeError? I
        think that would be misleading:
        [color=blue][color=green][color=darkred]
        >>> class Int(int):[/color][/color][/color]
        .... def __add__(self, other):
        .... return self/other
        ....[color=blue][color=green][color=darkred]
        >>> add(Int(1), 0)[/color][/color][/color]
        Traceback (most recent call last):
        File "<stdin>", line 1, in ?
        File "<stdin>", line 2, in add
        File "<stdin>", line 3, in __add__
        ZeroDivisionErr or: integer division or modulo by zero

        This may seem contrived, but for any non-trivial function the number of
        exceptions is open-ended, and trying to achieve reliability by handling a
        fixed set of exceptions is essentially asking for type declarations for a
        small portion of a function's signature - and a portion where its
        usefulness is debated even for statically typed languages (I think Java has
        it, but C sharp doesn't).
        Put your time to a better use and write a good test suite.

        Peter

        Comment

        • Peter Hansen

          #5
          Re: Identifying exceptions that can be raised

          dkcpub wrote:[color=blue]
          > Brian van den Broek wrote:
          >[color=green]
          >> If you mean you want a list of exceptions that a given function could
          >> raise, well, never mind :-)[/color]
          >
          > Yeah, that is what I mean. I write foo(), which calls a half-dozen
          > library functions. What exceptions is a caller of foo() going to have
          > to handle? It there an automated way of discovering that?[/color]

          Nope. That's that nasty ol' Java thinkin'. ;-)

          Basically, given the dynamicism that is Python's hallmark,
          you can't guarantee that any given function won't raise
          an arbitrary exception. I could write a function that
          could raise random exceptions, including ones it wasn't
          even previously aware of (by crawling the tree of classes
          starting at sys.modules and discovering new ones, perhaps).

          The usual approach is to have a caller catch exceptions
          *which it is capable of dealing with appropriately*, and
          ignore others. In some cases it's necessary to have a
          "generic" exception handler, such as at the top level of
          a thread, to catch and log all exceptions, but that's
          relatively rare.

          In contrast to Java code, you aren't forced to catch
          exceptions in a manner similar to the old-style approach
          to handling error values returned by functions (that is,
          by ignoring them). Instead you write useful code that
          actually explicitly catches only things it understands
          and can deal with. A breath of fresh air, really...

          All that said, you do sometimes find yourself pondering
          what exceptions a given function might raise and which
          you *do* want to handle properly. It's not always clear,
          and unfortunately short of examining the source or hoping
          that the author wrote decent documentation, you're out
          of luck.

          -Peter

          Comment

          • Andrew Dalke

            #6
            Re: Identifying exceptions that can be raised

            Peter Hansen wrote:[color=blue]
            > Nope. That's that nasty ol' Java thinkin'. ;-)
            >
            > Basically, given the dynamicism that is Python's hallmark,
            > you can't guarantee that any given function won't raise
            > an arbitrary exception.[/color]

            One of my puzzlements about Java 10 years ago or so was
            why it decided to go the "must declare every exception" route.

            Consider this simple and naive numeric integrator

            def integrate(f, start, end, n):
            delta = (end-start)/float(n)
            x = start + delta / 2
            sum = 0.0
            for i in range(n+1):
            sum = sum + f(x)
            x += delta
            return sum / (n+1)

            That function cannot define all the exceptions that can be
            raised because f itself can raise an arbitrary exception. Eg,

            def f1(x):
            return 1/max(5-x, 0)) # Can raise a divide-by-zero error

            integrate(f1, 0, 10, 5)

            Java handles that case by saying you don't need to declare
            system exceptions. Then consider

            def f2(x):
            fname = os.path.join("/cache/directory", str(x))
            if os.path.exists( fname):
            return float(open(fnam e, "r").read() )
            y = _f2(x)
            outfile = open(fname, "w")
            try:
            outfile.write(s tr(y))
            finally:
            outfile.close()
            return y

            integrate(f2, 0, 10, 10)

            If the file is not readable, or the directory not readable,
            then this might raise an IOError.

            How does the 'integrate' function declare that it can raise
            any of the errors that the integrator function 'f' might raise?

            Again, IOError might be considered a system-level error
            such that it doesn't need declaring. Then change it to
            polling some URL ("http://cache.server/" + str(x)) when the
            network is down, or getting it from some SQL database when
            the password is incorrect, or anything else that cannot be
            determined until actually calling f().

            It looks like the only thing to do is convert all such
            unhandled exceptions and wrap them in a catch-all generic
            exception. I think I've seen people do that. But if so,
            what's the point of having typed exceptions?

            Curiously-y'rs,

            Andrew
            dalke@dalkescie ntific.com

            Comment

            • Dan Sommers

              #7
              Re: Identifying exceptions that can be raised

              On Sat, 20 Nov 2004 07:18:32 GMT,
              Andrew Dalke <adalke@mindspr ing.com> wrote:
              [color=blue]
              > Peter Hansen wrote:[color=green]
              >> Nope. That's that nasty ol' Java thinkin'. ;-)
              >> Basically, given the dynamicism that is Python's hallmark,
              >> you can't guarantee that any given function won't raise
              >> an arbitrary exception.[/color][/color]
              [color=blue]
              > One of my puzzlements about Java 10 years ago or so was
              > why it decided to go the "must declare every exception" route.[/color]
              [color=blue]
              > Consider this simple and naive numeric integrator[/color]
              [color=blue]
              > def integrate(f, start, end, n):
              > delta = (end-start)/float(n)
              > x = start + delta / 2
              > sum = 0.0
              > for i in range(n+1):
              > sum = sum + f(x)
              > x += delta
              > return sum / (n+1)[/color]
              [color=blue]
              > That function cannot define all the exceptions that can be
              > raised because f itself can raise an arbitrary exception. Eg,[/color]

              [ cool example of f reading data from a file-system cache snipped ]
              [color=blue]
              > Again, IOError might be considered a system-level error
              > such that it doesn't need declaring. Then change it to
              > polling some URL ("http://cache.server/" + str(x)) when the
              > network is down, or getting it from some SQL database when
              > the password is incorrect, or anything else that cannot be
              > determined until actually calling f().[/color]

              And what if f has its own run-time plug-in mechanism?
              [color=blue]
              > It looks like the only thing to do is convert all such
              > unhandled exceptions and wrap them in a catch-all generic
              > exception. I think I've seen people do that. But if so,
              > what's the point of having typed exceptions?[/color]

              IMO (and maybe I'm just restating the obvious; it wouldn't be the first
              time <g>), "the list of exceptions f is allowed to raise" shouldn't be
              part of the interface of integrate, but rather "the list of exceptions
              integrate will handle gracefully" should be. Resumably, the caller of
              f, or some entity far enough up the call chain, anyway, knows something
              about f that integrate does not. In some cases, that entity could be a
              human sitting at an interactive console, and that human would like to
              know if/when f raises exceptions not handled by integrate.

              As to the original question, I agree: there's no way that integrate can
              know every exception f might raise, and there's no reason it should,
              either. f *must be content* with handling what it promises to handle
              and letting everything else pass through it unchanged. Logically, f is
              part of the *caller* of integrate rather than being among the functions
              integrate *calls*.

              Regards,
              Dan

              --
              Dan Sommers
              <http://www.tombstoneze ro.net/dan/>
              Never play leapfrog with a unicorn.

              Comment

              • Dan

                #8
                Re: Identifying exceptions that can be raised

                Peter Hansen wrote:[color=blue]
                > Nope. That's that nasty ol' Java thinkin'. ;-)[/color]

                Never used Java. Mostly just C. All in all, I like these exceptions
                better than C's error codes, because I mostly just write trivial little
                programs that would just print a message and exit if I detected an
                error--and exceptions do that automatically with no active checking on
                my part.

                But the thought occured to me that if I _did_ want to handle exceptions,
                I would have no idea what the possibilities even were.
                [color=blue]
                > All that said, you do sometimes find yourself pondering
                > what exceptions a given function might raise and which
                > you *do* want to handle properly.[/color]

                Exactly.

                /Dan

                --
                dedded at verizon dot net

                Comment

                • Peter Hansen

                  #9
                  Re: Identifying exceptions that can be raised

                  Dan wrote:[color=blue]
                  > the thought occured to me that if I _did_ want to handle exceptions,
                  > I would have no idea what the possibilities even were.[/color]

                  Here's another area where good unit testing can help (apologies
                  to those with an irrational negative reaction to test-driven
                  development concepts). By writing tests which exercise the routines
                  you are calling in various ways, you will often find which
                  exceptions are of interest but not perhaps documented clearly.

                  For example, the other day I discovered that if you attempt
                  to read or write from/to a closed file, you don't get what
                  you might expect (an IOError or an OSError), but in fact
                  you get a ValueError. Writing unit tests was what led to
                  this discovery. (Perhaps it's actually documented... I don't
                  know and didn't bother looking.)
                  [color=blue][color=green][color=darkred]
                  >>> f = open('test', 'w')
                  >>> f.close()
                  >>> f.write('testin g')[/color][/color][/color]
                  Traceback (most recent call last):
                  File "<stdin>", line 1, in ?
                  ValueError: I/O operation on closed file


                  -Peter

                  Comment

                  • Roy Smith

                    #10
                    Re: Identifying exceptions that can be raised

                    Peter Hansen <peter@engcorp. com> wrote:
                    [color=blue]
                    > For example, the other day I discovered that if you attempt
                    > to read or write from/to a closed file, you don't get what
                    > you might expect (an IOError or an OSError), but in fact
                    > you get a ValueError. Writing unit tests was what led to
                    > this discovery. (Perhaps it's actually documented... I don't
                    > know and didn't bother looking.)[/color]

                    What you are describing is essentially black-box testing. It may be a
                    valid procedure for QA purposes, but it's hardly a reasonable way to
                    write a program. Actually, it's worse than black-box testing.
                    Black-box testing says you should design your tests based only on the
                    documentation (functional spec, whatever) without looking at the source
                    code. You're saying you should write the code without even looking at
                    the documentation.

                    I'm a big fan of test-driven development, but not to the extent that I
                    feel I can ignore reading the documentation to see how something is
                    supposed to work. It took me about 15 seconds to find the page in the
                    library reference for file objects, where I immediately found:

                    ---------
                    close()
                    Close the file. A closed file cannot be read or written any more. Any
                    operation which requires that the file be open will raise a ValueError
                    after the file has been closed. Calling close() more than once is
                    allowed.
                    ---------

                    Computer Science is not an experimental science. In the old days of
                    biology, if I wanted to know what a certain gene did, I made my best
                    guess and designed an experiment to prove or disprove my theory. Repeat
                    as long as the funding holds out. These days, I pop the DNA into a
                    sequencing machine and read the source code. We may not fully
                    understand the language the program is written in, but it sure beats
                    poking at the thing with a stick and seeing what happens.

                    Comment

                    • Peter Hansen

                      #11
                      Re: Identifying exceptions that can be raised

                      Roy Smith wrote:[color=blue]
                      > Peter Hansen <peter@engcorp. com> wrote:
                      > What you are describing is essentially black-box testing. It may be a
                      > valid procedure for QA purposes, but it's hardly a reasonable way to
                      > write a program.[/color]

                      You provide nothing to back up this claim.
                      [color=blue]
                      > Actually, it's worse than black-box testing.[/color]

                      Nor this, of course.
                      [color=blue]
                      > Black-box testing says you should design your tests based only on the
                      > documentation (functional spec, whatever) without looking at the source
                      > code. You're saying you should write the code without even looking at
                      > the documentation.[/color]

                      Did I say that somewhere? I really don't think you can
                      find anything in what I said that equates to me recommending
                      that one should write code this way in the general case.
                      [color=blue]
                      > ---------
                      > close()
                      > Close the file. A closed file cannot be read or written any more. Any
                      > operation which requires that the file be open will raise a ValueError
                      > after the file has been closed. Calling close() more than once is
                      > allowed.
                      > ---------[/color]

                      In other words, the documentation in this case happens to align
                      with the actual behaviour of file objects.

                      Now I ask you, how often does documentation either not mention
                      the fact at all (which was the topic of this thread until now),
                      or -- perhaps less common with standard library code, but widespread
                      with other code -- mention things that are inaccurate and wrong?

                      And how often does the code actually behave the way the code
                      behaves?

                      In other words, which should one trust more, the documentation
                      or the actual observed behaviour?
                      [color=blue]
                      > Computer Science is not an experimental science.[/color]

                      Again, you've said nothing that in any way justifies this statement.

                      I'm not saying CS _is_ an experimental science, but I think
                      I would say that your implied statement that one should *never*
                      do this is fundamentally flawed.

                      Ultimately, however, this is a silly argument, because neither
                      you nor I write code solely in the manner I described, nor
                      in the manner you appear to be recommending (i.e. going exclusively
                      based on the documentation), so I'm not even sure why you
                      wrote...

                      As a final note, I'll point out that I was writing code for
                      a mock file system, and if you think doing that solely based
                      on the documentation is a good idea, I heartily recommend you
                      give it a go and see how useful your results actually are...

                      -Peter

                      Comment

                      • Roy Smith

                        #12
                        Re: Identifying exceptions that can be raised

                        I wrote:[color=blue][color=green]
                        >> You're saying you should write the code without even looking at
                        >> the documentation.[/color][/color]

                        Peter Hansen <peter@engcorp. com> wrote:[color=blue]
                        > Did I say that somewhere?[/color]

                        You said, "Perhaps it's actually documented... I don't know and didn't
                        bother looking." If I misinterpreted your statement, I apologize.
                        [color=blue]
                        > In other words, the documentation in this case happens to align
                        > with the actual behaviour of file objects.
                        >
                        > Now I ask you, how often does documentation either not mention
                        > the fact at all (which was the topic of this thread until now),
                        > or -- perhaps less common with standard library code, but widespread
                        > with other code -- mention things that are inaccurate and wrong?[/color]

                        Of course there is bad documentation in the world. If the documented
                        and actual behavior of the code differ, there's clearly a bug somewhere.
                        It could be that the documentation is wrong, or it could be that the
                        code is wrong. Both happen. Both kinds of bugs should be fixed when
                        they are discovered.
                        [color=blue]
                        > In other words, which should one trust more, the documentation
                        > or the actual observed behaviour?[/color]

                        Well, that's an interesting question, and I'm not sure there's a simple
                        answer to it. Certainly, if my testing determines that read() throws
                        ValueError under certain situations which are not documented, it would
                        be foolish for me to pretend that it didn't happen because the
                        documentation doesn't say so. But on the other hand, if I discovered
                        that math.pi had the value 3, I would be equally foolish to write code
                        which depended on that behavior.
                        [color=blue]
                        > Ultimately, however, this is a silly argument, because neither
                        > you nor I write code solely in the manner I described, nor
                        > in the manner you appear to be recommending (i.e. going exclusively
                        > based on the documentation), so I'm not even sure why you
                        > wrote...[/color]

                        I never recommended going exclusively from the docs. I started out by
                        saying:
                        [color=blue]
                        > I'm a big fan of test-driven development, but not to the extent that I
                        > feel I can ignore reading the documentation to see how something is
                        > supposed to work.[/color]

                        Anyway, it would look like both of us have unintentionally
                        misinterpreted what each other has said. I think in the end we both
                        agree that reading the docs is important, and testing is important too.
                        Both give us information which is unavailable from the other.

                        Comment

                        • Cameron Laird

                          #13
                          Re: Identifying exceptions that can be raised

                          In article <JQNnd.2125$hJ6 .1416@trndny01> , Dan <bounces@foo.or g> wrote:

                          Comment

                          • Jim Hefferon

                            #14
                            Re: Identifying exceptions that can be raised

                            Peter Hansen <peter@engcorp. com> wrote ..[color=blue]
                            > The usual approach is to have a caller catch exceptions
                            > *which it is capable of dealing with appropriately*, and
                            > ignore others. In some cases it's necessary to have a
                            > "generic" exception handler, such as at the top level of
                            > a thread, to catch and log all exceptions, but that's
                            > relatively rare.[/color]

                            I wonder if perhaps you don't write different kinds of programs than I
                            do.

                            For instance, I have a cgi program. One routine will get an id from a
                            httpd parameter, use it to reach into a database and fetch some xml,
                            and then pull information out of the xml for display. That I can
                            tell, there are about 100 exceptions that could be raised (the xml
                            parser is vague about what it could raise, and although the dB is a
                            bit better, it is not always clear what an exception means or under
                            what condidtions it could be raised). I'm left with the feeling that
                            for any amount of testing that I do (and I've found cgi hard to
                            automatically test), there is always another exception lurking out
                            there. I have a great deal of difficulty achieving the feeling that I
                            am consistently returning a sensible error screen to the user.

                            I've tried Java, and found it a slog, but for some programs knowing
                            which exceptions could be raised would be a comfort.
                            [color=blue]
                            > All that said, you do sometimes find yourself pondering
                            > what exceptions a given function might raise and which
                            > you *do* want to handle properly. It's not always clear,
                            > and unfortunately short of examining the source or hoping
                            > that the author wrote decent documentation, you're out
                            > of luck.[/color]

                            I second that.

                            Jim

                            Comment

                            • Dan

                              #15
                              Re: Identifying exceptions that can be raised

                              Cameron Laird wrote:[color=blue]
                              > I'm sympathetic. It bothers me no end when working
                              > with C and Java that documenters are as relaxed as
                              > I've found them to be in failing to document error
                              > conditions.[/color]

                              Then there was the DEC C library, in which free() returned an error code
                              on failure--and was so documented, but which was prototyped to return
                              void as required by the standard.

                              But I'll stop looking for the tool that finds all the exceptions that a
                              function can raise. :-)

                              /Dan

                              --
                              dedded att verizon dott net

                              Comment

                              Working...