Re: Newbie naive question ... int() throws ValueError

2012-05-12 Thread Ethan Furman

Devin Jeanpierre wrote:

On Fri, May 11, 2012 at 11:21 PM, Chris Angelico ros...@gmail.com wrote:

There are times when you want to catch all exceptions, though.
Top-level code will often want to replace exception tracebacks with
error messages appropriate to some external caller, or possibly log
the exception and return to some primary loop. Otherwise, though, most
code will just let unexpected exceptions through.


I'm not talking about unexpected exceptions. I'm saying, if I expect
invalid input for int, where should I go to find out how to deal with
said invalid input properly? How do I know that int raises ValueError
on failure, and not, for example, something like ArgumentError
(something that Python doesn't have) or (like chr) TypeError?

Apparently the answer is to read the documentation for ValueError.

It's a bit like putting the documentation on the return type for `map`
in the list documentation. Kinda hard to get there without already
knowing the answer.


Unit tests.  :)

~Ethan~
--
http://mail.python.org/mailman/listinfo/python-list


Re: Newbie naive question ... int() throws ValueError

2012-05-12 Thread Devin Jeanpierre
On Sat, May 12, 2012 at 8:27 AM, Karl Knechtel zahl...@gmail.com wrote:
 I really wish gmail picked up the mailing list as a default reply-to 
 address...

There is some labs thing that makes reply to all the default if you
click the button on the top-right. Unfortunately, that applies for
non-mailing-lists too...

 The easiest way is to try it. In fact, in most cases, this will be
 easier than looking it up in the documentation could ever be, because
 looking something up in documentation requires you to read through a
 bunch of documentation until you find key info like 'raises FooError
 in bar circumstance', and then interpret it; by trial and error, you
 see exactly what happens right away, and you can do it by just banging
 out a couple of lines on the REPL.

Eh, this doesn't make sense. Before I would ever try the int()
function, I would've read about it in the documentation -- otherwise
how would I know what it does at all? How would I even know that it exists?

What having to try-it-and-see does is give me extra steps to know what
it does. Instead of only reading the documentation, now I have to both
read the documentation *and* try it out in the interactive interpreter
to see its behaviour in a bunch of undocumented error cases.

What should actually happen is that the error cases should be
documented explicitly, so that I don't have to run around in the REPL
or orthogonal bits of documentation trying to figure out the behaviour
of the function.

 You should have already read the documentation for things like
 ValueError as a part of learning the language (i.e. the first time
 something raised a ValueError and you wanted to know what that meant);
 or at the very least you should have a good idea of what the
 standard exceptions are all named, and *develop an intuition* for
 which apply to what circumstances. As noted by others, you should not
 expect `int` to throw a `TypeError` when fed a bad string, because a
 `TypeError` means something is wrong with the type of some object,
 and the problem with the bad string isn't that it's a string (its
 type), but that the string contents are not interpretable as int (its
 value, hence ValueError).

And yet this is what ord does. Every rule has an exception.

I concede that reading the docs on ValueError is probably worth doing
the first time you see it. Although, it's also one of those exceptions
that has a clear name, so it isn't something everyone will do. I'm
not sure if I ever did it. And certainly the OP never looked there.

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


Re: Newbie naive question ... int() throws ValueError

2012-05-12 Thread Chris Angelico
On Sun, May 13, 2012 at 4:25 AM, Devin Jeanpierre
jeanpierr...@gmail.com wrote:
 What having to try-it-and-see does is give me extra steps to know what
 it does. Instead of only reading the documentation, now I have to both
 read the documentation *and* try it out in the interactive interpreter
 to see its behaviour in a bunch of undocumented error cases.

Point to note: The Python documentation tells you about the language.
Trying it in the interpreter tells you about your implementation.
There can be differences. I doubt there will be in something as simple
as casting to int, but in other functions, it wouldn't surprise me to
find that CPython (the one that most people think of as Python) and
IronPython, PyPy, or Jython have differences in what they can throw.

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


Re: Newbie naive question ... int() throws ValueError

2012-05-11 Thread Chris Angelico
On Fri, May 11, 2012 at 3:55 PM, John Terrak john.ter...@gmail.com wrote:
 I couldnt find anywhere in the documentation that int() can throw a 
 ValueError.
 I checked the The Python Language Reference, and the The Python
 Standard Library  to no avail.
 Did I missed something?

Unlike in Java, a function's list of things it can throw isn't part of
its signature. Instead of trying to catch every possible exception,
it's generally best to simply let exceptions propagate unless you KNOW
you're expecting them. In the case of int(), that would mean that you
catch ValueError if you're taking arbitrary strings from the user and
want integers (and then you could handle the ValueError by using a
default, for instance); but if you're writing a function that's
documented as taking a number as a parameter, let the exception go up
to the caller.

If it helps, think of all Python's exceptions as deriving from
RuntimeException - anything can happen, worry only about what really
worries you :)

 Thanks for your help - and sorry again for such a naive question.

It's a perfectly legitimate question, and you clearly did read the
docs before asking. Nothing to apologize for there!

Chris Angelico
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Newbie naive question ... int() throws ValueError

2012-05-11 Thread Terry Reedy

On 5/11/2012 1:55 AM, John Terrak wrote:


I couldnt find anywhere in the documentation that int() can throw a ValueError.
I checked the The Python Language Reference, and the The Python
Standard Library  to no avail.
Did I missed something?


To add to Chris' answer:

If the domain of a function is truly all Python objects, it cannot raise 
an error. I believe id(x) is such an example.


Even if the domain is intended to be all Python objects, you cannot be 
sure if the function uses any special method defined on the object or 
its class. For examples, type(x) *should* always work, but I would not 
be surprised if a buggy __getattribute__ method or buggy metaclass could 
result in an exception instead.


If the arguments for a function include a function, for example map(f, 
'abc'), then the passed function can raise any exception and hence the 
called function will pass along the exception unless, unusually, it 
catches it.


As to your specific question, if the domain of a function is a subset of 
types and values of allowed types, then you should expect that it can 
raise either TypeError or ValueError.

If the domain


So here is the question - if it is not in the documentation - how does
one find out the
exceptions that are thrown by a constructor, a method or a function?


One way is to try specific examples, as you did. Following what Chris 
said, especially do that for bad input whose exception you want to 
catch. Sometimes this is faster than trying to find the answer in the 
doc, and it gives the actual answer rather than the intended answer.



Example:  int(not_an_int)

int(not_an_int)

Traceback (most recent call last):
   File stdin, line 1, inmodule
ValueError: invalid literal for int() with base 10: 'not_an_int'


Some strings are legal input, hence not a TypeError, but not all, hence 
ValueError.



From what I gathered:

class int(object):
int(x[, base]) -  integer

   Convert a string or number to an integer, if possible.  A floating point
   argument will be truncated towards zero (this does not include a string
   representation of a floating point number!)  When converting a string, use
   the optional base.  It is an error to supply a base when converting a
   non-string.  If base is zero, the proper base is guessed based on the
   string content.  If the argument is outside the integer range a
   long object will be returned instead. 


'error' should say 'TypeError' as it is a TypeError to provide the wrong 
number of args. However, the current 3.3 manual entry is more accurate 
and informative, starting with the signature.


--
Terry Jan Reedy

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


Re: Newbie naive question ... int() throws ValueError

2012-05-11 Thread Christian Heimes
Am 11.05.2012 17:51, schrieb Terry Reedy:
 If the domain of a function is truly all Python objects, it cannot raise
 an error. I believe id(x) is such an example.

Even id() can raise an exception, for example MemoryError when you are
running out of memory.

Christian

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


Re: Newbie naive question ... int() throws ValueError

2012-05-11 Thread Chris Angelico
On Sat, May 12, 2012 at 2:15 AM, Christian Heimes li...@cheimes.de wrote:
 Am 11.05.2012 17:51, schrieb Terry Reedy:
 If the domain of a function is truly all Python objects, it cannot raise
 an error. I believe id(x) is such an example.

 Even id() can raise an exception, for example MemoryError when you are
 running out of memory.

KeyboardInterrupt can also be raised at (effectively) any time, but
I'm not sure that that really counts as id() raising the exception. If
I understand it correctly, MemoryError would be because the
interpreter can't allocate an int object for id's return value.

But these are definitely part of why you don't just catch all exceptions.

Hmm. What happens if the interpreter can't construct a MemoryError exception?

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


Re: Newbie naive question ... int() throws ValueError

2012-05-11 Thread Ian Kelly
On Fri, May 11, 2012 at 10:23 AM, Chris Angelico ros...@gmail.com wrote:
 Hmm. What happens if the interpreter can't construct a MemoryError exception?

I believe that a MemoryError instance is pre-allocated for just this
scenario.  You can see it in the result of gc.get_objects().

 [x for x in gc.get_objects() if isinstance(x, MemoryError)]
[MemoryError()]

Cheers,
Ian
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Newbie naive question ... int() throws ValueError

2012-05-11 Thread Chris Angelico
On Sat, May 12, 2012 at 3:12 AM, Ian Kelly ian.g.ke...@gmail.com wrote:
 I believe that a MemoryError instance is pre-allocated for just this
 scenario.

Ah, wise move. It's one of those largely-imponderables, like figuring
out how to alert the sysadmin to a router failure.

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


Re: Newbie naive question ... int() throws ValueError

2012-05-11 Thread John Terrak
Thank you all for your help.
Greatly appreciated.

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


Re: Newbie naive question ... int() throws ValueError

2012-05-11 Thread Devin Jeanpierre
On Fri, May 11, 2012 at 2:10 AM, Chris Angelico ros...@gmail.com wrote:
 Unlike in Java, a function's list of things it can throw isn't part of
 its signature. Instead of trying to catch every possible exception,
 it's generally best to simply let exceptions propagate unless you KNOW
 you're expecting them.

How am I supposed to know to expect them, if they are undocumented?
Trial and error? That seems like a poor replacement for documented
error conditions.

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


Re: Newbie naive question ... int() throws ValueError

2012-05-11 Thread Chris Angelico
On Sat, May 12, 2012 at 5:34 AM, Devin Jeanpierre
jeanpierr...@gmail.com wrote:
 On Fri, May 11, 2012 at 2:10 AM, Chris Angelico ros...@gmail.com wrote:
 Unlike in Java, a function's list of things it can throw isn't part of
 its signature. Instead of trying to catch every possible exception,
 it's generally best to simply let exceptions propagate unless you KNOW
 you're expecting them.

 How am I supposed to know to expect them, if they are undocumented?
 Trial and error? That seems like a poor replacement for documented
 error conditions.

Expect exceptions any time anything goes wrong. Don't try to code to
prevent them.

Here's an example. Suppose you write a function that takes a number
and returns that many copies of your club's charter. (Yeah, pretty
stupid, but examples usually are!)

def charter(copies):
return _chartertext * copies

Does this function need to catch any exceptions? No. Can that
expression throw exceptions? Totally! You might be given a non-number
(can't give foo copies); you might get a floating point (can't get
three-and-a-half copies); your charter text might have been replaced
with a pizza; the user might hit Ctrl-C right while it's copying; the
number might be so large that you run out of memory; all sorts of
things. But they're not your problems - they're your caller's
problems. If you caught all those exceptions, what would you do? You'd
have to signal the error conditions yourself, which probably means...
raising an exception.

There are times when you want to catch all exceptions, though.
Top-level code will often want to replace exception tracebacks with
error messages appropriate to some external caller, or possibly log
the exception and return to some primary loop. Otherwise, though, most
code will just let unexpected exceptions through.

This is one of those massively freeing leaps of thinking. Java binds
you to a bureaucracy of catching exceptions or declaring them (but
then still has RuntimeException - and I'm sure there've been MANY
programmers who just derive all their exceptions from that); Python
sets you free to care only about what you want to care about.

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


Re: Newbie naive question ... int() throws ValueError

2012-05-11 Thread Devin Jeanpierre
On Fri, May 11, 2012 at 11:21 PM, Chris Angelico ros...@gmail.com wrote:
 There are times when you want to catch all exceptions, though.
 Top-level code will often want to replace exception tracebacks with
 error messages appropriate to some external caller, or possibly log
 the exception and return to some primary loop. Otherwise, though, most
 code will just let unexpected exceptions through.

I'm not talking about unexpected exceptions. I'm saying, if I expect
invalid input for int, where should I go to find out how to deal with
said invalid input properly? How do I know that int raises ValueError
on failure, and not, for example, something like ArgumentError
(something that Python doesn't have) or (like chr) TypeError?

Apparently the answer is to read the documentation for ValueError.

It's a bit like putting the documentation on the return type for `map`
in the list documentation. Kinda hard to get there without already
knowing the answer.

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


Re: Newbie naive question ... int() throws ValueError

2012-05-11 Thread Chris Angelico
On Sat, May 12, 2012 at 2:11 PM, Devin Jeanpierre
jeanpierr...@gmail.com wrote:
 I'm not talking about unexpected exceptions. I'm saying, if I expect
 invalid input for int, where should I go to find out how to deal with
 said invalid input properly? How do I know that int raises ValueError
 on failure, and not, for example, something like ArgumentError
 (something that Python doesn't have) or (like chr) TypeError?

Ah, I see what you mean.

The easiest way to find out what exception gets thrown is to try it.
For obvious things like int(foo) you can simply test it in the
interactive interpreter; unusual cases you'll discover as you run your
script.

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