Re: [Tutor] Subclassing Exceptions

2012-01-09 Thread Chris Fuller
On Friday 06 January 2012, Steven D'Aprano wrote:
 Chris Fuller wrote:
  class Foo(SyntaxError):
  ...  def __init__(self, a,b,c):
  ...   self.args = (a,b,c)
  ...
  
  raise Foo(1,2,3)
  
  Traceback (most recent call last):
File stdin, line 1, in module
  
  __main__.Foo: None
  
  
  Inheriting from SyntaxError doesn't work!  When I create a new exception,
  I generally subclass from the built-in exception it most resembles, in
  case there was some reason to also catch it via an ancestor.  But I'm
  not sure if that is really all that useful an idea in practice.  How do
  you folk do it?
 
 What do you mean, doesn't work? It looks like it works to me. You get a
 Foo exception, exactly as expected. The error message isn't what you
 expect, because you're making unwarranted assumptions about SyntaxError
 and how it works.
 
 In general, when you override a method, you take full responsibility to
 perform everything that the superclass method was supposed to do. In this
 case, you fail to assign to msg as well as args. It is safer to overload a
 
 message rather than override it:
   class Spam(SyntaxError):
 ... def __init__(self, *args):
 ... if args:
 ... args  = (I pity the fool who made a mistake,) +
 args[1:] ... super(Spam, self).__init__(*args)
 ...
 
   raise Spam('you made a mistake', 1, 2)
 
 Traceback (most recent call last):
File stdin, line 1, in module
 __main__.Spam: I pity the fool who made a mistake
 
 
 
 Unfortunately, there's no real consistency in what arguments exceptions are
 expected to take. The best thing is to read the docs, if they have any, or
 use introspection and trial and error to work out what they do.
 
   try:
 ... raise SyntaxError(you made a mistake)
 ... except SyntaxError, err:
 ... pass
 ...
 
   err.msg
 
 'you made a mistake'
 
 
 See dir(err) for more; you can use help(SyntaxError) but unfortunately it
 isn't very useful.
 
 
 You probably shouldn't inherit from SyntaxError, since it represents syntax
 errors in the Python code being interpreted or compiled. Any syntax error
 in your own data structures should be independent of SyntaxError.

In Python: Essential Reference, David Beazley recommends that the parameters 
of the exception be assigned to the args attribute, so it is passed all the 
way through the traceback.  You will observe that the last element in the 
traceback loses this information when subclassed from SyntaxError.  This isn't 
a problem when the whole traceback is laid out before you, but can come into 
play with automated tools that catch/log/manipulate exceptions.  This behavior 
of exceptions isn't apparently mentioned in the canonical documentation, 
however.

I had the same thought about not wanting to mix syntax errors in the data with 
syntax errors in the code, but that applies to any exception, really.  In 
fact, it's better to inherit from a more derived class, because when you catch 
an ancestor, you'll be grabbing less greedily at the possible coding errors.  
Which suggests that giving a damn about built-in ancestors of user-defined 
exceptions is a losing proposition, now that I think about it.

Cheers
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Subclassing Exceptions

2012-01-07 Thread Lie Ryan

On 01/07/2012 03:56 PM, Steven D'Aprano wrote:

Chris Fuller wrote:

You probably shouldn't inherit from SyntaxError, since it represents
syntax errors in the Python code being interpreted or compiled. Any
syntax error in your own data structures should be independent of
SyntaxError.


I'd say a syntactical error in your own data structure is a kind of 
ValueError.


___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


[Tutor] Subclassing Exceptions

2012-01-06 Thread Chris Fuller
I had an interesting experience today.

Python 2.7.1 (r271:86832, Nov 28 2010, 19:31:37) 
[GCC 4.4.5] on linux2
Type help, copyright, credits or license for more information.
 class Foo(Exception):
...  def __init__(self, a,b,c):
...   self.args = (a,b,c)
... 
 raise Foo(1,2,3)
Traceback (most recent call last):
  File stdin, line 1, in module
__main__.Foo: (1, 2, 3)
 class Foo(SyntaxError):
...  def __init__(self, a,b,c):
...   self.args = (a,b,c)
... 
 raise Foo(1,2,3)
Traceback (most recent call last):
  File stdin, line 1, in module
__main__.Foo: None


Inheriting from SyntaxError doesn't work!  When I create a new exception, I 
generally subclass from the built-in exception it most resembles, in case 
there was some reason to also catch it via an ancestor.  But I'm not sure if 
that is really all that useful an idea in practice.  How do you folk do it?

By the way, inheriting from StandardError, the direct ancestor of  
SyntaxError, works as expected, and its parent is Exception.

Cheers
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Subclassing Exceptions

2012-01-06 Thread Devin Jeanpierre
 Inheriting from SyntaxError doesn't work!  When I create a new exception, I
 generally subclass from the built-in exception it most resembles, in case
 there was some reason to also catch it via an ancestor.  But I'm not sure if
 that is really all that useful an idea in practice.  How do you folk do it?

If somebody wanted to catch a ValueError, would they also mean to
catch my error? (The same with SyntaxError and so on). Probably not.
If they would, then I raise the relevant exception. It is very
possible to accidentally catch the wrong thing if you put too much in
a try block, and I don't like making that any easier.

-- Devin

On Fri, Jan 6, 2012 at 10:24 PM, Chris Fuller
cfuller...@thinkingplanet.net wrote:
 I had an interesting experience today.

 Python 2.7.1 (r271:86832, Nov 28 2010, 19:31:37)
 [GCC 4.4.5] on linux2
 Type help, copyright, credits or license for more information.
 class Foo(Exception):
 ...  def __init__(self, a,b,c):
 ...   self.args = (a,b,c)
 ...
 raise Foo(1,2,3)
 Traceback (most recent call last):
  File stdin, line 1, in module
 __main__.Foo: (1, 2, 3)
 class Foo(SyntaxError):
 ...  def __init__(self, a,b,c):
 ...   self.args = (a,b,c)
 ...
 raise Foo(1,2,3)
 Traceback (most recent call last):
  File stdin, line 1, in module
 __main__.Foo: None


 Inheriting from SyntaxError doesn't work!  When I create a new exception, I
 generally subclass from the built-in exception it most resembles, in case
 there was some reason to also catch it via an ancestor.  But I'm not sure if
 that is really all that useful an idea in practice.  How do you folk do it?

 By the way, inheriting from StandardError, the direct ancestor of
 SyntaxError, works as expected, and its parent is Exception.

 Cheers
 ___
 Tutor maillist  -  Tutor@python.org
 To unsubscribe or change subscription options:
 http://mail.python.org/mailman/listinfo/tutor
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Subclassing Exceptions

2012-01-06 Thread Steven D'Aprano

Chris Fuller wrote:


class Foo(SyntaxError):

...  def __init__(self, a,b,c):
...   self.args = (a,b,c)
... 

raise Foo(1,2,3)

Traceback (most recent call last):
  File stdin, line 1, in module
__main__.Foo: None


Inheriting from SyntaxError doesn't work!  When I create a new exception, I 
generally subclass from the built-in exception it most resembles, in case 
there was some reason to also catch it via an ancestor.  But I'm not sure if 
that is really all that useful an idea in practice.  How do you folk do it?


What do you mean, doesn't work? It looks like it works to me. You get a Foo 
exception, exactly as expected. The error message isn't what you expect, 
because you're making unwarranted assumptions about SyntaxError and how it works.


In general, when you override a method, you take full responsibility to 
perform everything that the superclass method was supposed to do. In this 
case, you fail to assign to msg as well as args. It is safer to overload a 
message rather than override it:


 class Spam(SyntaxError):
... def __init__(self, *args):
... if args:
... args  = (I pity the fool who made a mistake,) + 
args[1:]
... super(Spam, self).__init__(*args)
...

 raise Spam('you made a mistake', 1, 2)
Traceback (most recent call last):
  File stdin, line 1, in module
__main__.Spam: I pity the fool who made a mistake



Unfortunately, there's no real consistency in what arguments exceptions are 
expected to take. The best thing is to read the docs, if they have any, or use 
introspection and trial and error to work out what they do.


 try:
... raise SyntaxError(you made a mistake)
... except SyntaxError, err:
... pass
...
 err.msg
'you made a mistake'


See dir(err) for more; you can use help(SyntaxError) but unfortunately it 
isn't very useful.



You probably shouldn't inherit from SyntaxError, since it represents syntax 
errors in the Python code being interpreted or compiled. Any syntax error in 
your own data structures should be independent of SyntaxError.





--
Steven



___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Subclassing Exceptions

2012-01-06 Thread Steven D'Aprano

Devin Jeanpierre wrote:

Inheriting from SyntaxError doesn't work!  When I create a new exception, I
generally subclass from the built-in exception it most resembles, in case
there was some reason to also catch it via an ancestor.  But I'm not sure if
that is really all that useful an idea in practice.  How do you folk do it?


If somebody wanted to catch a ValueError, would they also mean to
catch my error? (The same with SyntaxError and so on). Probably not.


If your error represents a value error, then yes they would.

But in that case, why should I subclass ValueError instead of just using 
ValueError itself? Writing my own exceptions is only useful if I intend to 
give the caller the *choice* of either treating my exception the same or 
different from ValueError: that is, if my error is a more specific kind of 
ValueError. If it is not a specific kind of value error, then just use the 
generic built-in ValueError exception instead.



try:
x = some_function()
except MyValueError:
# treat my errors specially
except ValueError:
# any other kind of ValueError caught here

vs.

try:
x = some_function()
except ValueError:
# any kind of ValueError caught here, including MyValueError


The same goes for all exception types, although in practice I find that I 
generally only subclass ValueError.




--
Steven
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor