Newbie question: what exceptions are thrown by FTP class

Discussion in 'Ruby' started by Simon Morgan, Dec 8, 2009.

  1. Simon Morgan

    Simon Morgan Guest

    Hi,

    I'm a Ruby newbie, and may have a daft question: how do I determine what
    exceptions are thrown by different classes, so I know which ones to
    catch etc?

    As a starting exercise I'm writiing a program to do some FTPing, so at
    the moment I'm specifically interested in the FTP class, but will have a
    generic question for other classes.

    Is this documented somewhere obvious that I'm misssing?

    Thanks in advance.
    --
    Posted via http://www.ruby-forum.com/.
     
    Simon Morgan, Dec 8, 2009
    #1
    1. Advertising

  2. Simon Morgan wrote:

    > [H]ow do I determine what exceptions are thrown by different classes, so I know which ones to catch etc?
    > I'm specifically interested in the FTP class ...
    >
    > Is this documented somewhere obvious that I'm misssing?
    >


    Can you point me towards the documentation for that FTP class?
    --
    Posted via http://www.ruby-forum.com/.
     
    Aldric Giacomoni, Dec 8, 2009
    #2
    1. Advertising

  3. Simon Morgan

    Simon Morgan Guest

    Simon Morgan, Dec 8, 2009
    #3
  4. The Net::FTP documentation does tell you some exceptions that it can
    raise, and if you really care about the detail you can just look at the
    source, since it's all written in Ruby, and at the top you'll find

    module Net

    # :stopdoc:
    class FTPError < StandardError; end
    class FTPReplyError < FTPError; end
    class FTPTempError < FTPError; end
    class FTPPermError < FTPError; end
    class FTPProtoError < FTPError; end
    # :startdoc:

    But often you don't care. Exceptions form a hierarchy, and the ones you
    want to catch are usually either under StandardError or RuntimeError
    (itself a subclass of StandardError)

    A simple "rescue" by itself is the same as "rescue StandardError".

    If you want to capture *all* exceptions then rescue Exception, but this
    is usually not a good idea as it will also capture fatal errors - e.g.
    NoMemoryError, SyntaxError, and Interrupt (ctrl-C)

    For Net::FTP I would suggest:

    begin
    ...
    rescue IOError, SystemCallError, Net::FTPError
    ...
    end

    to catch everything socket-related and any protocol errors raised within
    Net::FTP, without catching things which are normally programmer bugs
    like NameError or ArgumentError.

    Google "ruby exception hierarchy" for more info.
    --
    Posted via http://www.ruby-forum.com/.
     
    Brian Candler, Dec 8, 2009
    #4
  5. Simon Morgan

    Simon Morgan Guest

    Brian,

    Thanks for your reply, it’s very much appreciated.

    Really I’m after something along the lines of what Java’s JavaDoc might
    give which lists the thrown exceptions and the reasons why e.g.:
    http://java.sun.com/javase/6/docs/api/ (I’m from a Java background). Do
    you know if this exists or if there is a tool that can generate this
    sort of info?

    I did try looking at the source however the problem is just the time it
    takes to go through everything to find what throws what, and this is
    fairly error-prone and time-consuming; e.g. if I call nlst() without a
    network connection, the exception is thrown from nlst > retrlines >
    voidcmd > putline, which is throwing an error from a call to
    TCPSocket.write...

    Thanks for the specific info on FTP though, I’ll work with that for now
    -- although I guess I may still need to search through all the code to
    find the different IOError and SystemCallError instances, to see if I’d
    want to treat them differently.

    I hope you don’t think I’m being awkward, as I do value your reply and
    time you put in.

    Regards

    Simon
    --
    Posted via http://www.ruby-forum.com/.
     
    Simon Morgan, Dec 8, 2009
    #5
  6. Simon Morgan wrote:
    > Really I’m after something along the lines of what Java’s JavaDoc might
    > give which lists the thrown exceptions and the reasons why


    If the author includes that in the API documentation, then you'll have
    it; if the author doesn't, then I'm afraid you won't.

    In the case of Net::FTP you can see that the author decided to remove
    all of the exception classes from the documentation :)stopdoc:),
    presumably to avoid cluttering it up.

    > or if there is a tool that can generate this
    > sort of info?


    The documentation you are currently looking at is generated via rdoc,
    which basically extracts comments and method signatures from the code.
    However, Ruby is a very dynamic language and it's not possible to
    determine from static source analysis which exceptions may or may not be
    thrown.

    This isn't just nitpicking. It's quite common in Ruby to pass around and
    use objects of 'unrelated' classes at runtime: 'unrelated' in the sense
    of not sharing a common ancestor class other than Object. Rather, they
    implement the same 'duck-type' interface. In the case of Net::FTP you
    might arrange that it uses a SOCKSSocket instead of a Socket, for
    example, and SOCKSSocket could have its own set of exceptions that it
    raises (SOCKS authentication error, for example).

    You could argue that if it raises a different exception under similar
    circumstances then that's a duck-type violation - the duck goes honk
    instead of quack. Unfortunately, this aspect of duck-typing is often
    overlooked.

    Anyway: there's no formal "interface" in ruby, which means objects can
    implement whatever methods they feel like, and raise whatever exceptions
    they feel like, and change their behaviour at runtime whenever they feel
    like.

    You probably find this dirty. However it's what enables all sorts of
    goodness, such as ActiveRecord being able to define model classes at
    runtime based on the columns in your database. The advice I give to you
    is: relax, and have good unit test coverage.

    > I did try looking at the source however the problem is just the time it
    > takes to go through everything to find what throws what


    It's pretty obvious in this case. All you have to do is look for classes
    of which Exception is an ancestor (or StandardError or RuntimeError),
    and they are all bundled together at the top of the file. It's just
    convention, rather than rigidly enforced.

    > and this is
    > fairly error-prone and time-consuming; e.g. if I call nlst() without a
    > network connection, the exception is thrown from nlst > retrlines >
    > voidcmd > putline, which is throwing an error from a call to
    > TCPSocket.write...


    Indeed. Hence my advice to be generic in your rescue strategy.

    But *why* would you be calling nlst on a connection which isn't open?
    Isn't that a programmer error, and therefore you shouldn't be catching
    the exception at all?

    > -- although I guess I may still need to search through all the code to
    > find the different IOError and SystemCallError instances, to see if I’d
    > want to treat them differently.


    Those are pretty low-level - for example, Errno::ECONNREFUSED is a
    subclass of SystemCallError, so to determine all possible exceptions
    when opening a socket you'll really need to look at the documentation
    for the unix open(2) call and the possible errno values which it can
    set.

    It has to be said that Ruby's own core documentation is a long way from
    complete.

    Regards,

    Brian.
    --
    Posted via http://www.ruby-forum.com/.
     
    Brian Candler, Dec 9, 2009
    #6
  7. 2009/12/8 Simon Morgan <>:
    > Really I=92m after something along the lines of what Java=92s JavaDoc mig=

    ht
    > give which lists the thrown exceptions and the reasons why e.g.:
    > http://java.sun.com/javase/6/docs/api/ (I=92m from a Java background). Do
    > you know if this exists or if there is a tool that can generate this
    > sort of info?


    There can be no tool that works under all circumstances because a)
    exceptions are not declared as checked exceptions in Java are and b)
    the code of a Ruby class can change any time (including throwing new
    exceptions). While that may sound a bit theoretical it explains why
    probably nobody has bothered so far to come up with the tool you are
    requesting. (Note, even in Java you can create such a situation by
    using unchecked exceptions and delegate at some place in code to
    instances of different classes all of which do not necessarily have to
    be known at compile time.)

    You can look at the sources as Brian suggested or try to provoke
    different error situations (i.e. using a hostname that does not exist,
    using a wrong user, retrieving a file which you know is not on the
    server etc.) and see what happens.

    More often than not though it is probably sufficient to catch some
    basic errors as Brian suggested.

    Kind regards

    robert


    --=20
    remember.guy do |as, often| as.you_can - without end
    http://blog.rubybestpractices.com/
     
    Robert Klemme, Dec 9, 2009
    #7
  8. Simon Morgan

    Simon Morgan Guest

    >> Really I’m after something along the lines of what Java’s JavaDoc might
    >> give which lists the thrown exceptions and the reasons why

    >
    > If the author includes that in the API documentation, then you'll have
    > it; if the author doesn't, then I'm afraid you won't.


    Sigh. I feared that would be the case.


    > In the case of Net::FTP you can see that the author decided to remove
    > all of the exception classes from the documentation :)stopdoc:),
    > presumably to avoid cluttering it up.


    Yes I spotted that, kinda frustrating that I have to look at the source
    code to find some of the errors raised. Ah well.


    >> and this is
    >> fairly error-prone and time-consuming; e.g. if I call nlst() without a
    >> network connection, the exception is thrown from nlst > retrlines >
    >> voidcmd > putline, which is throwing an error from a call to
    >> TCPSocket.write...

    >
    > Indeed. Hence my advice to be generic in your rescue strategy.
    >
    > But *why* would you be calling nlst on a connection which isn't open?
    > Isn't that a programmer error, and therefore you shouldn't be catching
    > the exception at all?
    >


    If the network connection dies between opening and calling nlst(), for
    example.


    > It has to be said that Ruby's own core documentation is a long way from
    > complete.


    Sigh.


    Thanks very much for your time Brian, it's very much appreciated, I'll
    see how I adapt.

    --
    Posted via http://www.ruby-forum.com/.
     
    Simon Morgan, Dec 9, 2009
    #8
  9. Simon Morgan wrote:
    >> But *why* would you be calling nlst on a connection which isn't open?
    >> Isn't that a programmer error, and therefore you shouldn't be catching
    >> the exception at all?
    >>

    >
    > If the network connection dies between opening and calling nlst(), for
    > example.


    OK, I see.

    In that case you would probably get something like an Errno::EPIPE
    (writing to a socket where the read end is closed).

    I don't think you really want to enumerate all the possibilities though.
    Just rescue SystemCallError which is the parent of all the exceptions in
    module Errno.
    --
    Posted via http://www.ruby-forum.com/.
     
    Brian Candler, Dec 9, 2009
    #9
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Winista

    Unhandled Exceptions thrown

    Winista, Mar 22, 2006, in forum: ASP .Net
    Replies:
    0
    Views:
    409
    Winista
    Mar 22, 2006
  2. Adam Maass
    Replies:
    5
    Views:
    431
    Sudsy
    Jul 22, 2003
  3. Mike Schilling
    Replies:
    2
    Views:
    364
    Mike Schilling
    Jul 16, 2003
  4. Replies:
    1
    Views:
    341
    =?ISO-8859-1?Q?Erik_Wikstr=F6m?=
    Aug 16, 2007
  5. D. Buck
    Replies:
    2
    Views:
    595
    D. Buck
    Jun 29, 2004
Loading...

Share This Page