[EMAIL PROTECTED] a écrit :
On Aug 19, 10:19 am, eliben <[EMAIL PROTECTED]> wrote:

P.S. There's a common case where a method is passed a filename, to do
something with a file (say, read data). Should the method catch the
errors possibly thrown by open(), or leave it to the caller ?

You want to look up Easier to Ask Forgivness than Permission (EAFP)
which is touted as the "canonical" error-handling paradigm for Python.
This would give rise to the following function:

  def do_something(filename):
    try:
      f = open(filename)
    except IOError:
      return err("File %s not found" % filename)
    ...

where err is a function that generates an error object that your
application understands.

Sorry but that's IMHO totally broken.

This "error object" is useless (heck, we *do* have exceptions, don't we ???), *returning* it ruins the whole point of structured exception handling and take us back to infamous C error code checking (which are almost never checked), and - icing on the cake - the error message is very possibly wrong and misleading (IOError dont necessarily mean 'file not found'). This kind of exception "handling" manages to be worse than no exception handling at all.

I personally think this is sloppy because you
have to couple the exception type with the function --- between file()
and open() in Python 2 and 3, a NameError is thrown with open() in
Python 3

??? I suspect this has nothing to do with any error happening while opening the file. NameError means the name doesn't exists in the current namespace nor it's enclosing namespaces. Could it be possible that open() has been removed from Py3k ?

and an IOError is thrown in the other three cases <bashes
head against keyboard>. The alternative is

  def do_something(filename):
    if not os.access(filename,os.R_OK):
      return err(...)
    f = open(filename)
    ...

This gets even worse. race condition... Things can change between the call to os.access and the call to open. Well-known antipattern.

or, (and this last one I actually used for a web application)

  def do_something(filename):
    if not os.access(filename,os.R_OK):
      raise MyApplicationsExceptionType("File not found...")

You loose all the useful information you'd have from an IOError raised by a direct call to open...

    f = open(filename)
    ...


... IOError that you're still likely to see happen anyway.

The last one has the advantage that you can write a request handler
like this

  def handle_http_request(...):
    func = specific_handler_func(...)
    try:
      response = func(...)
      return response
    except MyApplicationsExceptionType as exc: #3.0 syntax
      return error_response(exc,...)


If you want to raise a different exception type - which can indeed be a sensible thing to do, depending on the context -, you can do it safely and keep accurate informations:

def do_something(filename):
    try:
        f = open(filename)
    except IOError, e
       raise MyApplicationsExceptionType(e.msg)
       # could even pass whole traceback etc
    # etc...


Exceptions you don't expect (i.e. bugs)

An exception you don't expect is not necessarily a bug. Try unplugging your lan cable while writing to a socket connected to another computer...

(snip)

If you are writing a library (for instance using a file for persistent
storage), then the answer to your question is "don't catch the
exception." Clients will expect the usual exception to be thrown when
a bad file name is passed.

Indeed.
--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to