Re: try-except with no exceptions

2016-10-15 Thread Nobody
On Thu, 13 Oct 2016 15:06:25 +0100, Daiyue Weng wrote:

> I know that such try-catch usage is generally a bad practice, since it
> can't locate the root of the exceptions.
> 
> I am wondering how to correct the code above

Either identify the specific exceptions you're expecting, or if you're
interested in "any error", use "except StandardError". That will catch
"errors" but won't catch e.g. KeyboardInterrupt or SystemExit.

Trying to further narrow the set of possible exceptions is often
impossible considering the use of duck typing.

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


Re: try-except with no exceptions

2016-10-13 Thread Ben Finney
Daiyue Weng  writes:

> I am wondering how to correct the code above (what it tries to do is
> basically trying one processing block, if not working, running another
> block of code in except). Also a warning 'Too broad exception clause'
> will be generated.

Yes. You need to be *very* clear about which specific “not working”
conditions you expect to handle, and catch only those.

Also, having identified which specific conditions you will handle, you
need to break complex statements and expressions into simpler ones, and
only place reduce the ‘try’ block to only those statements which will
encounter those conditions. Move everything else outside the ‘try …
except …’ altogether.

-- 
 \ “In prayer, it is better to have a heart without words than |
  `\ words without heart.” —Mohandas K. Gandhi |
_o__)  |
Ben Finney

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


Re: try-except with no exceptions

2016-10-13 Thread Peter Otten
Daiyue Weng wrote:

> Hi, I have seen code using try_except with no exceptions,
> 
> from dateutil import parser
> 
> try:
> from_date = datetime.datetime.strptime(parameters['from_date'],
> '%Y-%m-%d %H:%M:%S.%f')
> to_date = datetime.datetime.strptime(parameters['to_date'],
> '%Y-%m-%d %H:%M:%S.%f')
> except:
> from_date = parser.parse(parameters['from_date'])
> to_date = parser.parse(parameters['to_date'])
> 
> 
> I know that such try-catch usage is generally a bad practice, since it
> can't locate the root of the exceptions.
> 
> I am wondering how to correct the code above (what it tries to do is
> basically trying one processing block, if not working, running another
> block of code in except). Also a warning 'Too broad exception clause'
> will be generated.

Is it intentional that both times have to be parsed by the same function?
If not I'd do

def parse_date(datestr):
try:
return datetime.datetime.strptime(datestr, '%Y-%m-%d %H:%M:%S.%f')
except ValueError:
return dateutil.parser.parse(datestr)


from_date = parse_date(parameters['from_date'])
to_date = parse_date(parameters['to_date'])

Exceptions other than ValueError are probably hints that the program logic 
is flawed, so I'd rather have them bubble up.

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


Re: try-except with no exceptions

2016-10-13 Thread Jussi Piitulainen
Daiyue Weng writes:

> Hi, I have seen code using try_except with no exceptions,
>
> from dateutil import parser
>
> try:
> from_date = datetime.datetime.strptime(parameters['from_date'],
> '%Y-%m-%d %H:%M:%S.%f')
> to_date = datetime.datetime.strptime(parameters['to_date'],
> '%Y-%m-%d %H:%M:%S.%f')
> except:
> from_date = parser.parse(parameters['from_date'])
> to_date = parser.parse(parameters['to_date'])
>
>
> I know that such try-catch usage is generally a bad practice, since it
> can't locate the root of the exceptions.
>
> I am wondering how to correct the code above (what it tries to do is
> basically trying one processing block, if not working, running another
> block of code in except). Also a warning 'Too broad exception clause'
> will be generated.

Since help(datetime.strptime) didn't tell, I experimented with
datetime.strptime a bit. It seems to raise a ValueError when a string is
not formatted according to the pattern or has some component out of
range, and TypeError when given a non-string to parse. Tracebacks
indicate the exception type.

There's no point in catching KeyError, because the except clause would
do the same thing again.

try:
   # try with datetime.datetime.strptime
   ...
except (ValueError, TypeError):
   # try with dateutil.parser.parse
   ...

Also: https://docs.python.org/3/tutorial/errors.html
-- 
https://mail.python.org/mailman/listinfo/python-list


try-except with no exceptions

2016-10-13 Thread Daiyue Weng
Hi, I have seen code using try_except with no exceptions,

from dateutil import parser

try:
from_date = datetime.datetime.strptime(parameters['from_date'],
'%Y-%m-%d %H:%M:%S.%f')
to_date = datetime.datetime.strptime(parameters['to_date'],
'%Y-%m-%d %H:%M:%S.%f')
except:
from_date = parser.parse(parameters['from_date'])
to_date = parser.parse(parameters['to_date'])


I know that such try-catch usage is generally a bad practice, since it
can't locate the root of the exceptions.

I am wondering how to correct the code above (what it tries to do is
basically trying one processing block, if not working, running another
block of code in except). Also a warning 'Too broad exception clause'
will be generated.


cheers
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: try..except with empty exceptions

2015-04-12 Thread Cameron Simpson

On 12Apr2015 16:33, Cameron Simpson c...@zip.com.au wrote:
Finally, if we were to expunge support for except:, one would also need a 
cast iron guarrentee that no exception could possibly occur which was not a 
subclass of BaseException. I'd expect that to mean that raise of a 
non-instance of BaseException to itself raise a TypeError.


And I see that Steven D'Aprano has already pointed out PEP 352:

 http://www.python.org/dev/peps/pep-0352/

which is marked Status: Final. It says:

 The raise statement will be changed to require that any object passed to it 
 must inherit from BaseException. This will make sure that all exceptions fall 
 within a single hierarchy that is anchored at BaseException [2] . This also 
 guarantees a basic interface that is inherited from BaseException. The change 
 to raise will be enforced starting in Python 3.0 (see the Transition Plan 
 below).


Hmm. Not in 2.7? I can see the breakage it could cause, but where does that 
leave me? I think I could probably move to catching Exception almost across the 
board even in 2.5+ and feel pretty good.


Cheers,
Cameron Simpson c...@zip.com.au

If your new theorem can be stated with great simplicity, then there
will exist a pathological exception.- Adrian Mathesis
--
https://mail.python.org/mailman/listinfo/python-list


Re: try..except with empty exceptions

2015-04-12 Thread Cameron Simpson

On 12Apr2015 14:18, Steven D'Aprano steve+comp.lang.pyt...@pearwood.info 
wrote:

On Sun, 12 Apr 2015 09:08 am, Cameron Simpson wrote:

Also, IMO, a bare except: syntax is far more pleasing to the eye than
except magic_exception_name_that+gets_everything:.


And that is exactly what makes bare excepts an attractive nuisance!

I'm going to channel a newbie, cowboy or just plain lazy coder:
I have a block of code with a bug. Bugs are bad. I know, I'll wrap it in

try:
   block
except:
   pass

and the bug will go away!


And haven't we all seen that _many_ times on this list:-)


It looks nice and requires relatively little typing. It seems like something
you should do, but it doesn't fix the problem, chances are it just makes it
worse.


And do not get me started on Makefiles which finish every compile command in 
2/dev/null :-(



I've spotted many real-world examples where bare excepts mask the
presence of actual bugs, where the intention is clearly to catch a single
exception: [...]
Forcing people to type an exception will discourage such cowboy coding. If
the choice is between

   except BaseException:

instead of the lazy except: version, and

   except IndexError:

which do you think people will write?


I fear that the just-beyond-beginner might write Exception, but your point is 
well taken.



Also, I wish
BaseException were just spelled Exception, if it has to be used.


Most of the time, catch everything should mean catching Exception, not
BaseException. Broadly speaking, built-in exceptions which are
considered errors inherit from Exception, and the small number that don't
are used for some variation of control-flow:

StopIteration
GeneratorExit
KeyboardInterrupt
SysExit

Most of the time when people say catch everything they mean catch all
errors, i.e. Exception, rather than don't let the user interrupt the code
using KeyboardInterrupt.


Yes, I see that this is true.

And I have special pain in some of my code which then causes me to specificly 
catch NameError ahead of my bare (or mostly bare) excepts because that usually 
indicates some stupid typo on my part, causing silent breakage and debugging 
hell. Ghastly.



See also PEP 352:
http://www.python.org/dev/peps/pep-0352/


Thank you for this.

Cheers,
Cameron Simpson c...@zip.com.au

To be or not to be?Not to be.
   - John Slater (Arnold Schwartzenegger),
 _Macbeth_ (_The_Last_Action_Hero_)
--
https://mail.python.org/mailman/listinfo/python-list


Re: try..except with empty exceptions

2015-04-12 Thread Cameron Simpson

On 12Apr2015 09:21, Chris Angelico ros...@gmail.com wrote:

On Sun, Apr 12, 2015 at 9:08 AM, Cameron Simpson c...@zip.com.au wrote:

Catching all exceptions isn't terribly common, _except_ in service routines
that wrap unknown operations. Classic example from my Asynchron class: [...]

 try:
   r = func(*a, **kw)
 except:
   self.exc_info = sys.exc_info
 else:
   self.result = r

All sorts of things like thread pools and other worker functions, and
run-forever daemons like mail filers that can have arbitrary exceptions
occur in (partly) third party code eg from config files; you need to catch
any unknown exception and fail the specific action, but continue the main
daemon operation.

And since I use this code in Python 2, and since not all exceptions are
BaseException subclasses, I need the bare syntax.


Fair enough. Do you know how often you actually catch stuff that
wouldn't be caught by except BaseException:?


I don't know and I'm not sure I care (but discussion below). I would need to 
examine carefully what they were. Looking at the 2.7.9 doco for Exception it 
almost looks like that is what I should often want. (Though I think I have some 
circumstances where I might prefer BaseException.)



I would guess it's
pretty rare. In fact, you can find out.

try:
  r = func(*a, **kw)
except BaseException:
  self.exc_info = sys.exc_info
except:
  self.exc_info = sys.exc_info
  emit_warning()
   else:
  self.result = r

You could simply mandate that, from version X.Y of your Asynchron
module onward, old-style classes must not be thrown.


Except that Asynchron, like several of the other circumstances, is expected to 
be used with arbitrary callables from outside sources.



Also, IMO, a bare except: syntax is _far_ more pleasing to the eye than
except magic_exception_name_that+gets_everything:. Also, I wish
BaseException were just spelled Exception, if it has to be used.



I'm -0.1 on the idea myself. I consider except: succinct and evocative,
and prefer it to except BaseException:.


What you're looking at here is exactly why it's not spelled that way.
The normal thing to do is NOT to catch absolutely everything, but to
allow KeyboardInterrupt and SystemExit to continue to bubble up.
That's spelled except Exception.


Yes. But can I guarrentee that those are the only two? The 2.7.9 doco says:

  exception Exception
  All built-in, non-system-exiting exceptions are derived from this class.

I suppose I could consider that clear, but certainly in case of 
KeyboardInterrupt I might want to involve cleanup actions. I'll ignore 
interactive situations; messy.


My whole point here is that the bare except catches too much for normal use, 
and therefore should _not_ be pleasing to the eye. The thing you should most 
often be doing is except ValueError or equivalent; forcing you to put at 
least _some_ name into the exception clause emphasizes that being specific

is not the unusual case.


Yes. But it seems to me that normal use generally means the situation where 
one catches a quite narrow set of exceptions for which particular recoveries 
are well defined.


However, when I want all exceptions, that really is what I mean. I need to 
think quite carefully about KeyboardInterrupt and SystemExit. The former is 
guarrenteed to be delivered to the main thread IIRC and I'd want to catch that 
specificly in my main() function, if at all. And I suspect that SystemExit 
really shouldn't be stopped; if something untoward is calling it, should it not 
succeed? Or be exposed and then hunted down and killed!


So your argument for except Exception: is quite compelling for many 
situations where I do currently use except:. I will review them and have a 
proper think.


However, my Asynchron class really is a little special. I use Asynchron to 
underpin a bunch of classes whose instances get fulfilled later, especially 
callables that get queued and run at a suitable time (or which get run in 
response to some external long awaited event). So, example sketch:


 L = Later()
 ...
 # LF is a LateFunction, a subclass of Asynchron
 LF = L.defer(function, *a, **kw)
 ...
 try:
   result = LF()
 except Whatever as e:
   ...

My Later class serves a purpose much like the futures module and I suppose a 
LateFunction is somewhat like a future.


Anyway, at some point in the above example function gets called (by the 
infrastructure of Later) with the supplied arguments as the Later processes 
its queue.


The user can collect the result by calling LF() whenever they like, as though 
they were calling function() directly.  If the function has already run, the 
value is returned or whatever exception _it_ raised is raised now. Otherwise it 
blocks until the function is run; same behaviour for the caller except for a 
delay.


So in this situation: should I catch and defer KeyboardInterrupt or SystemExit?  
Maybe not, but the clean/naive implementation says to catch 

Re: try..except with empty exceptions

2015-04-12 Thread Chris Angelico
On Sun, Apr 12, 2015 at 4:33 PM, Cameron Simpson c...@zip.com.au wrote:
 On 12Apr2015 09:21, Chris Angelico ros...@gmail.com wrote:
 Fair enough. Do you know how often you actually catch stuff that
 wouldn't be caught by except BaseException:?


 I don't know and I'm not sure I care (but discussion below). I would need to
 examine carefully what they were. Looking at the 2.7.9 doco for Exception it
 almost looks like that is what I should often want. (Though I think I have
 some circumstances where I might prefer BaseException.)

A very good reason to avoid except: and always put some name in
there. Forces you to think about which of the two you want.

 You could simply mandate that, from version X.Y of your Asynchron
 module onward, old-style classes must not be thrown.

 Except that Asynchron, like several of the other circumstances, is expected
 to be used with arbitrary callables from outside sources.

Yes, but you have version requirements already. You can't expect
someone to deploy Asynchron on Python 2.1, I would guess. In the same
way, you can simply state that raising what Steven referred to as an
NBEE will cause problems.

 What you're looking at here is exactly why it's not spelled that way.
 The normal thing to do is NOT to catch absolutely everything, but to
 allow KeyboardInterrupt and SystemExit to continue to bubble up.
 That's spelled except Exception.


 Yes. But can I guarrentee that those are the only two? The 2.7.9 doco says:

   exception Exception
   All built-in, non-system-exiting exceptions are derived from this
 class.

 I suppose I could consider that clear, but certainly in case of
 KeyboardInterrupt I might want to involve cleanup actions. I'll ignore
 interactive situations; messy.

That's what try/finally is for. You can do your cleanup without caring
exactly what was raised.

 Yes. But it seems to me that normal use generally means the situation
 where one catches a quite narrow set of exceptions for which particular
 recoveries are well defined.

That is, in fact, the most normal way to catch exceptions. What you're
doing here is a distinctly abnormal situation: creating a protective
boundary between two separate layers.

 However, when I want all exceptions, that really is what I mean. I need to
 think quite carefully about KeyboardInterrupt and SystemExit. The former is
 guarrenteed to be delivered to the main thread IIRC and I'd want to catch
 that specificly in my main() function, if at all. And I suspect that
 SystemExit really shouldn't be stopped; if something untoward is calling it,
 should it not succeed? Or be exposed and then hunted down and killed!

That's what you have to decide, yeah. Chances are you just want to
catch Exception in a lot of the cases.

 However, my Asynchron class really is a little special. I use Asynchron to
 underpin a bunch of classes whose instances get fulfilled later, especially
 callables that get queued and run at a suitable time (or which get run in
 response to some external long awaited event). ...
 Anyway, at some point in the above example function gets called (by the
 infrastructure of Later) with the supplied arguments as the Later
 processes its queue.

 So in this situation: should I catch and defer KeyboardInterrupt or
 SystemExit?  Maybe not, but the clean/naive implementation says to catch
 absolutely everything.

That is a tough one. I would support either of BaseException and
Exception for this case, and whichever you pick, there will be a time
when you wish you'd picked the other. But at least now you get a
chance to think about it.

 Finally, if we were to expunge support for except:, one would also need a
 cast iron guarrentee that no exception could possibly occur which was not a
 subclass of BaseException. I'd expect that to mean that raise of a
 non-instance of BaseException to itself raise a TypeError.

As of Py3, that is indeed the case. In Py2, you can at least run
python -3 and get a DeprecatoinWarning any time you attempt to raise
a NBEE; I don't know if you can make that into an error. But even if
you can't, all you have to do is explain that it's equivalent to any
other form of shooting yourself in the foot.

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


Re: try..except with empty exceptions

2015-04-12 Thread Cameron Simpson

On 12Apr2015 17:00, Chris Angelico ros...@gmail.com wrote:

On Sun, Apr 12, 2015 at 4:33 PM, Cameron Simpson c...@zip.com.au wrote:

[...]

That's what try/finally is for. You can do your cleanup without caring
exactly what was raised.


Hmm, yes.

[...]

However, my Asynchron class really is a little special. I use Asynchron to
underpin a bunch of classes whose instances get fulfilled later, especially
callables that get queued and run at a suitable time (or which get run in
response to some external long awaited event). ...
Anyway, at some point in the above example function gets called (by the
infrastructure of Later) with the supplied arguments as the Later
processes its queue.

So in this situation: should I catch and defer KeyboardInterrupt or
SystemExit?  Maybe not, but the clean/naive implementation says to catch
absolutely everything.


That is a tough one. I would support either of BaseException and
Exception for this case, and whichever you pick, there will be a time
when you wish you'd picked the other. But at least now you get a
chance to think about it. [...]


On reflection I'm probably going to go after a bunch of my in-other-thread 
things that handle unknown callables and do something like:


 self.result = None
 self.exc_info = None
 try:
   r = func(...)
 except Exception:
   self.exc_info = sys.exc_info
 except BaseException as e:
   self.exc_info = sys.exc_info
   exception(unexpected BaseException: %s, e)
 else:
   self.result = r

to catch and report the weirdos. And I might write a little decorator to report 
and reraise NameError to avoid certain times of silent asynchronous failure I 
have to debug.


Colour me convinced, and +0.5 for proposals to retire bare except.

Behold:

 [hg/css]fleet* hg clone . ../css-remove-except:
 updating to branch default
 2871 files updated, 0 files merged, 0 files removed, 0 files unresolved

Unnamed branch to change my practices:-)

Cheers,
Cameron Simpson c...@zip.com.au

... It beeped and said Countdown initiated. Is that bad?
--
https://mail.python.org/mailman/listinfo/python-list


Re: try..except with empty exceptions

2015-04-11 Thread Ian Kelly
On Apr 11, 2015 5:06 AM, Steven D'Aprano 
steve+comp.lang.pyt...@pearwood.info wrote:

 Yes, I agree that Python's behaviour here is better than the alternative.
 Having except () catch nothing is consistent with the behaviour with
 other tuples, so I'm okay with that. But it still surprised me :-)

There's another alternative that I haven't seen suggested yet. An empty
tuple could be considered an indication of a programming error and raise a
chained ValueError.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: try..except with empty exceptions

2015-04-11 Thread Chris Angelico
On Sun, Apr 12, 2015 at 7:37 AM, Cameron Simpson c...@zip.com.au wrote:
 On 11Apr2015 21:21, Chris Angelico ros...@gmail.com wrote:

 But I agree, it would be very nice if Python 3 could have abolished
 the truly confusing part of this, where except: catches everything.
 Forcing people to spell it except BaseException: would fix all of
 this. How hard is it to deprecate and then remove that, same as string
 exceptions were removed?


 I guess I'll go over there to oppose it then.

 Why? It makes it harder to write portable python 2/3 code and does not add
 any semantic advantage.

 Unless there's a common root exception class in Python 2, which I believe
 there isn't, you can't catch all exceptions in python 2 without the
 except: syntax.  Which means the _only_ way to have some code in both 2
 and 3 that does it requires 2 codebases.

 As one who tries to have his code run in both 2 (usually recent 2, like
 2.6/2.7) and 3, this change would cause a signification breakage for me
 without bringing any semantic benefits.

Can you give an example of a place where in Py2 you absolutely have to
catch everything, and don't have control over the code, *and* are
trying to do a one-codebase routine with Py3 compatibility? If you're
trying for 2/3 compatibility, you'll need to have all your exceptions
derive from BaseException anyway.

At very worst, it could be turned into a compat-only syntax feature,
like the uspam noise prefix on Unicode strings - serving absolutely
no purpose in Py3 code, and ideally, able to be removed at some point
post-2020.

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


Re: try..except with empty exceptions

2015-04-11 Thread Chris Angelico
On Sun, Apr 12, 2015 at 4:49 AM, Ian Kelly ian.g.ke...@gmail.com wrote:
 On Apr 11, 2015 5:06 AM, Steven D'Aprano
 steve+comp.lang.pyt...@pearwood.info wrote:

 Yes, I agree that Python's behaviour here is better than the alternative.
 Having except () catch nothing is consistent with the behaviour with
 other tuples, so I'm okay with that. But it still surprised me :-)

 There's another alternative that I haven't seen suggested yet. An empty
 tuple could be considered an indication of a programming error and raise a
 chained ValueError.

Not really a lot of point. Just as with isinstance, an empty tuple
simply matches nothing. Why go to the effort of rejecting it?

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


Re: try..except with empty exceptions

2015-04-11 Thread Chris Angelico
On Sun, Apr 12, 2015 at 6:04 AM, Chris Angelico ros...@gmail.com wrote:
 On Sun, Apr 12, 2015 at 4:49 AM, Ian Kelly ian.g.ke...@gmail.com wrote:
 On Apr 11, 2015 5:06 AM, Steven D'Aprano
 steve+comp.lang.pyt...@pearwood.info wrote:

 Yes, I agree that Python's behaviour here is better than the alternative.
 Having except () catch nothing is consistent with the behaviour with
 other tuples, so I'm okay with that. But it still surprised me :-)

 There's another alternative that I haven't seen suggested yet. An empty
 tuple could be considered an indication of a programming error and raise a
 chained ValueError.

 Not really a lot of point. Just as with isinstance, an empty tuple
 simply matches nothing. Why go to the effort of rejecting it?

(At least, I assume you're not putting a literal empty tuple in. This
would be useful only in cases where the tuple is provided
dynamically.)

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


Re: try..except with empty exceptions

2015-04-11 Thread Cameron Simpson

On 11Apr2015 21:21, Chris Angelico ros...@gmail.com wrote:

But I agree, it would be very nice if Python 3 could have abolished
the truly confusing part of this, where except: catches everything.
Forcing people to spell it except BaseException: would fix all of
this. How hard is it to deprecate and then remove that, same as string
exceptions were removed?


I guess I'll go over there to oppose it then.

Why? It makes it harder to write portable python 2/3 code and does not add any 
semantic advantage.


Unless there's a common root exception class in Python 2, which I believe there 
isn't, you can't catch all exceptions in python 2 without the except: syntax.  
Which means the _only_ way to have some code in both 2 and 3 that does it 
requires 2 codebases.


As one who tries to have his code run in both 2 (usually recent 2, like 
2.6/2.7) and 3, this change would cause a signification breakage for me without 
bringing any semantic benefits.


Without vigorous use of the time machine I don't see a fix here.

For the record, I would be ok (but not for) never having had bare except if 
all exceptions had always had a common root.


Hmm. Can I catch object? Sounds awful, but might work.

Cheers,
Cameron Simpson c...@zip.com.au

EMACS: Escape Meta Alt Control Shift
--
https://mail.python.org/mailman/listinfo/python-list


Re: try..except with empty exceptions

2015-04-11 Thread Steven D'Aprano
On Sat, 11 Apr 2015 12:23 pm, Dave Angel wrote:

 On 04/10/2015 09:42 PM, Steven D'Aprano wrote:
 On Sat, 11 Apr 2015 05:31 am, sohcahto...@gmail.com wrote:

 It isn't document because it is expected.  Why would the exception get
 caught if you're not writing code to catch it?  If you write a function
 and pass it a tuple of exceptions to catch, I'm not sure why you would
 expect it to catch an exception not in the tuple.  Just because the
 tuple
 is empty doesn't mean that it should catch *everything* instead.  That
 would be counter-intuitive.

 Really? I have to say, I expected it.


 
 I'm astounded at your expectation.  That's like saying a for loop on an
 empty list ought to loop on all possible objects in the universe.

Not really.

If we wrote:

for x in:
# Missing sequence leads to an infinite loop

*then* your analogy would be excellent, but it isn't. With for loops, we
iterate over each item in the sequence, hence an empty sequence means we
don't iterate at all.

But with try...except, an empty exception list means to catch *everything*,
not nothing:

try: ...
except a,b,c: # catches a, b, c

try: ...
except a,b: # catches a, b

try: ...
except a: # catches a

try: ...
except: # catches EVERYTHING, not nothing


Putting (a, b, c) into a tuple shouldn't make a difference, and it doesn't,
unless the tuple is empty. That surprised me.

t = a, b, c
try:
except t:  # same as except a,b,c

t = a, b
try:
except t:  # same as except a,b

t = a,
try:
except t:  # same as except a

t = ()
try: 
except t:  # NOT THE SAME as bare except.


I can see the logic behind the current behaviour. If you implement except
clauses like this pseudo-code:


for exc in exceptions:
if raised_exception matches exc: catch it


then an empty tuple will naturally lead to nothing being caught. That
doesn't mean it isn't surprising from the perspective that an empty
exception list (i.e. a bare except) should be analogous to an empty tuple.


 The tuple lists those exceptions you're interested in, and they are
 tried, presumably in order, from that collection.  If none of those
 match, then the logic will advance to the next except clause.  If the
 tuple is empty, then clearly none will match.

Yes, that makes sense, and I agree that it is reasonable behaviour from one
perspective. But its also reasonable to treat except (): as analogous to
a bare except.

[...]
 try:
  spam()
 except:
  # Implicitly an empty tuple.
 
 No, an omitted item is not the same as an empty tuple.

You are correct about Python as it actually is, but it could have been
designed so that except (): was equivalent to a bare except.


 If it were, then 
 we wouldn't have the problem of bare excepts, which are so tempting to
 novices.  There's plenty of precedent in many languages for a missing
 item being distinct from anything one could actually supply.

Let us put aside the fact that some people misuse bare excepts, and allow
that there are some uses for it. Now, in Python 2.6 and later, you can
catch everything by catching BaseException. But in older versions, you
could raise strings as well, and the only way to catch everything is with a
bare except.

If you want to write a function that takes a list of things to catch,
defaulting to everything, in Python 2.6+ we can write:

def spam(things_to_catch=BaseException):
try:
do_stuff()
except things_to_catch:
handle_exception()


but in older versions you have to write this:

def spam(things_to_catch=None):
if things_to_catch is None:
try:
do_stuff()
except:
handle_exception()
else:
try:
do_stuff()
except things_to_catch:
handle_exception()


This violates Don't Repeat Yourself. Any time you have a missing item being
distinct from anything one could actually supply, you have a poor design.

Anyway, in modern Python (2.6 onwards), now that string exceptions are gone,
you can supply something to catch everything. Or nothing, for that matter:

BaseException  # catch everything
Exception  # catch errors
(A, B, C)  # Just A, B or C or their subclasses
A  # Just A (or its subclasses)
()  # Catch nothing.

so I suppose that having an empty tuple mean catch nothing is better than
having it catch everything.



-- 
Steven

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


Re: try..except with empty exceptions

2015-04-11 Thread Terry Reedy

On 4/10/2015 9:42 PM, Steven D'Aprano wrote:


try:
 spam()
except:
 # Implicitly an empty tuple.
 pass


No, specified as equivalent to 'except BaseException:' (or 'except 
(BaseException,):', either of which are different from 'except ():'.
An expression-less except clause, if present, must be last; it matches 
any exception.


--
Terry Jan Reedy

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


Re: try..except with empty exceptions

2015-04-11 Thread Cameron Simpson

On 10Apr2015 19:38, Rustom Mody rustompm...@gmail.com wrote:

On Saturday, April 11, 2015 at 7:53:31 AM UTC+5:30, Dave Angel wrote:

On 04/10/2015 09:42 PM, Steven D'Aprano wrote:
 On Sat, 11 Apr 2015 05:31 am, sohcahtoa82 wrote:
 It isn't document because it is expected.  Why would the exception get
 caught if you're not writing code to catch it?  If you write a function
 and pass it a tuple of exceptions to catch, I'm not sure why you would
 expect it to catch an exception not in the tuple.  Just because the tuple
 is empty doesn't mean that it should catch *everything* instead.  That
 would be counter-intuitive.

 Really? I have to say, I expected it.

I'm astounded at your expectation.  That's like saying a for loop on an
empty list ought to loop on all possible objects in the universe.


To work, this analogy should also have two python syntaxes like this:

Normal for-loop:
for var in iterable:
 suite

Empty for-loop:
for:
 suite


Well, to throw an anaolgy in the mix, the shell has a bare for syntax.

 list='a b c'
 for x in $list
 do  echo $x
 done

echoes a, b and c as you might expect.

This:

 for x
 do  echo $x
 done

echoes the command line arguments. (Which is extremely useful.)

But as with Python, the missing iteration means a _default_ source of 
iteration, not _no_ iteration.


To continue the analogy, this:

 list=
 for x in $list
 do  echo $x
 done

echoes nothing. As I would hope Steven would expect.

Importantly, in both Python and the shell you have a way to specify nothing.  

If the empty tuple were to mean catch everything then there would not be a 
way to express catch nothing. Bad bad bad!


Consider this a proof that Python's current meanings for bare except and 
except () are sensible, using a proof by contradiction.


Cheers,
Cameron Simpson c...@zip.com.au
--
https://mail.python.org/mailman/listinfo/python-list


Re: try..except with empty exceptions

2015-04-11 Thread Serhiy Storchaka

On 11.04.15 10:11, Steven D'Aprano wrote:

Anyway, in modern Python (2.6 onwards), now that string exceptions are gone,
you can supply something to catch everything. Or nothing, for that matter:

BaseException  # catch everything


Not everything.

 class A: pass
...
 try: raise A
... except BaseException: pass
...
Traceback (most recent call last):
  File stdin, line 1, in module
__main__.A: __main__.A instance at 0xb707982c


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


Re: try..except with empty exceptions

2015-04-11 Thread Dave Angel

On 04/11/2015 03:11 AM, Steven D'Aprano wrote:

On Sat, 11 Apr 2015 12:23 pm, Dave Angel wrote:


On 04/10/2015 09:42 PM, Steven D'Aprano wrote:

On Sat, 11 Apr 2015 05:31 am, sohcahto...@gmail.com wrote:


It isn't document because it is expected.  Why would the exception get
caught if you're not writing code to catch it?  If you write a function
and pass it a tuple of exceptions to catch, I'm not sure why you would
expect it to catch an exception not in the tuple.  Just because the
tuple
is empty doesn't mean that it should catch *everything* instead.  That
would be counter-intuitive.


Really? I have to say, I expected it.




I'm astounded at your expectation.  That's like saying a for loop on an
empty list ought to loop on all possible objects in the universe.


Not really.

If we wrote:

 for x in:
 # Missing sequence leads to an infinite loop

*then* your analogy would be excellent, but it isn't. With for loops, we
iterate over each item in the sequence, hence an empty sequence means we
don't iterate at all.

But with try...except, an empty exception list means to catch *everything*,
not nothing:


No an empty exception list means to catch nothing.  A *missing* 
exception list means catch everything, but that's a different syntax


try: ...
except a,b,c: # catches a, b, c

try: ...
except a,b: # catches a, b

try: ...
except a: # catches a


try: ...
except (a,)   #catches a

try: ...
except ()  #catches nothing, as expected



try: ...
except: # catches EVERYTHING, not nothing



Different syntax.  No reason for it to pretend that it's being given an 
empty tuple or list.




Putting (a, b, c) into a tuple shouldn't make a difference, and it doesn't,
unless the tuple is empty. That surprised me.

t = a, b, c
try:
except t:  # same as except a,b,c

t = a, b
try:
except t:  # same as except a,b

t = a,
try:
except t:  # same as except a

t = ()
try:
except t:  # NOT THE SAME as bare except.


Of course not.  It's empty, so it catches nothing. Just like 'for'




I can see the logic behind the current behaviour. If you implement except
clauses like this pseudo-code:


for exc in exceptions:
 if raised_exception matches exc: catch it


then an empty tuple will naturally lead to nothing being caught. That
doesn't mean it isn't surprising from the perspective that an empty
exception list (i.e. a bare except) should be analogous to an empty tuple.


Why should it??  It's a different syntax, with different rules.  Perhaps 
it should have been consistent, but then it's this statement that's 
surprising, not the behavior with an empty tuple.






The tuple lists those exceptions you're interested in, and they are
tried, presumably in order, from that collection.  If none of those
match, then the logic will advance to the next except clause.  If the
tuple is empty, then clearly none will match.


Yes, that makes sense, and I agree that it is reasonable behaviour from one
perspective. But its also reasonable to treat except (): as analogous to
a bare except.

[...]

try:
  spam()
except:
  # Implicitly an empty tuple.


No, an omitted item is not the same as an empty tuple.


You are correct about Python as it actually is, but it could have been
designed so that except (): was equivalent to a bare except.


Only by changing the bare except behavior.





If it were, then
we wouldn't have the problem of bare excepts, which are so tempting to
novices.  There's plenty of precedent in many languages for a missing
item being distinct from anything one could actually supply.


Let us put aside the fact that some people misuse bare excepts, and allow
that there are some uses for it. Now, in Python 2.6 and later, you can
catch everything by catching BaseException. But in older versions, you
could raise strings as well, and the only way to catch everything is with a
bare except.

If you want to write a function that takes a list of things to catch,
defaulting to everything, in Python 2.6+ we can write:

def spam(things_to_catch=BaseException):
 try:
 do_stuff()
 except things_to_catch:
 handle_exception()


but in older versions you have to write this:

def spam(things_to_catch=None):
 if things_to_catch is None:
 try:
 do_stuff()
 except:
 handle_exception()
 else:
 try:
 do_stuff()
 except things_to_catch:
 handle_exception()


This violates Don't Repeat Yourself. Any time you have a missing item being
distinct from anything one could actually supply, you have a poor design.


Yep, and it happens all the time.  For example, mylist[a,b,-1]What 
value can I use for b to mean the whole list?


There are others more grotesque, but I can't think of any at this moment.



Anyway, in modern Python (2.6 onwards), now that string exceptions are gone,
you can supply something to catch everything. Or nothing, for that matter:

BaseException  # catch everything
Exception  # catch errors

Re: try..except with empty exceptions

2015-04-11 Thread Steven D'Aprano
On Sun, 12 Apr 2015 07:37 am, Cameron Simpson wrote:

 On 11Apr2015 21:21, Chris Angelico ros...@gmail.com wrote:
But I agree, it would be very nice if Python 3 could have abolished
the truly confusing part of this, where except: catches everything.
Forcing people to spell it except BaseException: would fix all of
this. How hard is it to deprecate and then remove that, same as string
exceptions were removed?
 
 I guess I'll go over there to oppose it then.
 
 Why? It makes it harder to write portable python 2/3 code and does not add
 any semantic advantage.

I don't think it does make it harder to write hybrid 2+3 applications.

The thing is, in 3, you *must* inherit from BaseException. String exceptions
are gone (they were removed in 2.6, so if you're still using them, you code
won't even run in 2.6 or 2.7). Old-style classes are gone, so your classic
exceptions will automatically be promoted to new-style classes.

class MyException:
pass

In 2.x code, that can be raised and caught. But not in 3.x, so if you are
writing hybrid code you have to change that anyway! It's surely a trivial
change:

class MyException(Exception):
pass


Now you can raise it in both 2.x and 3.x, and you can catch it with except
Exception, as recommended.

Now, *technically* there are things that are possible with classic classes
in 2.x which are hard or impossible once you inherit from Exception, but
(1) I don't imagine that exceptions will use them, and (2) you still have
to deal with that when migrating anyway, so you are no worse off.

[To be precise, I'm referring to things like the ability to override dunder
methods on a per-instance basis. Want to give this specific instance, and
no other, the ability to support + addition? You can with classic classes,
but not easily with new-style classes. But who is going to want to do that
for an exception?]



 Unless there's a common root exception class in Python 2, which I believe
 there isn't, you can't catch all exceptions in python 2 without the
 except: syntax. 

Correct.


 Which means the _only_ way to have some code in both 2 
 and 3 that does it requires 2 codebases.

You would think so, but not really. The thing is, if you want to use a
single codebase, you cannot *raise* strings, or classic classes that don't
inherit from BaseException, not even in your 2.x code. Since you aren't
raising them, there's no need to catch them!

In hybrid code running under 2.x, a non-BaseException exception (NBEE) is a
bug to be fixed. The fact that you are no longer catching it in 2.x is a
good thing, because that forces you to find the offending code which raises
the NBEE and fix it.


 
 As one who tries to have his code run in both 2 (usually recent 2, like
 2.6/2.7) and 3, this change would cause a signification breakage for me
 without bringing any semantic benefits.

I think that the only way that would be true is if you are referring to a
*library*, rather than an application. In other words, you have:

- a single code base with hybrid 2+3 code;

- your users are integrating it with other people's code (perhaps their own)
  which you do not control, i.e. it is a library, not an application;

- that 3rd party code raises string exceptions (up to 2.5) or classic NBEE;

- you have to catch those exceptions, and cannot just say to your users we
  don't support non-BaseException exceptions any more.

Life is tough for library authors who want to support old code :-(


The solution, as I see it, would be to extract only the bits of your code
that does the exception handling, and split it into two separate files:

# catcher2.py
from common import dostuff
try: 
...
except BaseException:
dostuff()
except:
warnings.warn(fix your code, you neanderthal!)
dostuff()

# catcher3.py
from common import dostuff
try:
...
except BaseException:
dostuff()


and then conditionally import one or the other. Alternatively, you can use
exec, and a single file.

I wouldn't say that either solution thrills me. If I were in that position,
I would simply document that string exceptions and classic-class exceptions
are no longer supported, and make my users responsible for fixing or
replacing the third-party code that raises such things.



 Without vigorous use of the time machine I don't see a fix here.
 
 For the record, I would be ok (but not for) never having had bare
 except if all exceptions had always had a common root.
 
 Hmm. Can I catch object? Sounds awful, but might work.

No.

http://bugs.python.org/issue2291

See also PEP 352, which explains some of the motivation of the post 2.4
changes to exceptions, and the expected timeline for changes leading up to
3.x. (Some of the PEP is a bit obsolete, it still refers to Python 2.9
being the last of the 2.x series.)

http://www.python.org/dev/peps/pep-0352/



-- 
Steven

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


Re: try..except with empty exceptions

2015-04-11 Thread Steven D'Aprano
On Sun, 12 Apr 2015 09:08 am, Cameron Simpson wrote:

 Also, IMO, a bare except: syntax is far more pleasing to the eye than
 except magic_exception_name_that+gets_everything:.


And that is exactly what makes bare excepts an attractive nuisance!

I'm going to channel a newbie, cowboy or just plain lazy coder:


I have a block of code with a bug. Bugs are bad. I know, I'll wrap it in

try:
block
except:
pass

and the bug will go away!

It looks nice and requires relatively little typing. It seems like something
you should do, but it doesn't fix the problem, chances are it just makes it
worse. I've spotted many real-world examples where bare excepts mask the
presence of actual bugs, where the intention is clearly to catch a single
exception:

try:
return mylist[0]
except:
# empty list
return None


Forcing people to type an exception will discourage such cowboy coding. If
the choice is between

except BaseException:

instead of the lazy except: version, and

except IndexError:

which do you think people will write?



 Also, I wish
 BaseException were just spelled Exception, if it has to be used.

Most of the time, catch everything should mean catching Exception, not
BaseException. Broadly speaking, built-in exceptions which are
considered errors inherit from Exception, and the small number that don't
are used for some variation of control-flow:

StopIteration
GeneratorExit
KeyboardInterrupt
SysExit


Most of the time when people say catch everything they mean catch all
errors, i.e. Exception, rather than don't let the user interrupt the code
using KeyboardInterrupt.

See also PEP 352:

http://www.python.org/dev/peps/pep-0352/

-- 
Steven

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


Re: try..except with empty exceptions

2015-04-11 Thread Steven D'Aprano
On Sat, 11 Apr 2015 06:22 pm, Serhiy Storchaka wrote:

 On 11.04.15 10:11, Steven D'Aprano wrote:
 Anyway, in modern Python (2.6 onwards), now that string exceptions are
 gone, you can supply something to catch everything. Or nothing, for that
 matter:

 BaseException  # catch everything
 
 Not everything.
 
   class A: pass
 ...
   try: raise A
 ... except BaseException: pass
 ...
 Traceback (most recent call last):
File stdin, line 1, in module
 __main__.A: __main__.A instance at 0xb707982c

Hmmm, I thought that starting from 2.6 exceptions had to inherit from
BaseException. Thanks for the correction.


[steve@ando ~]$ python2.7 -c class A: pass
raise A()
Traceback (most recent call last):
  File string, line 2, in module
__main__.A: __main__.A instance at 0xb7ebb1ac


[steve@ando ~]$ python3.3 -c class A: pass
raise A()
Traceback (most recent call last):
  File string, line 2, in module
TypeError: exceptions must derive from BaseException


Ahah! So it's 3.x only that catching BaseException should catch everything.

In 2.6, Python stopped supporting string exceptions:

[steve@ando ~]$ python2.6 -c raise 'spam'
Traceback (most recent call last):
  File string, line 1, in module
TypeError: exceptions must be old-style classes or derived from
BaseException, not str

(glad that at least I remembered that part correctly!)




-- 
Steven

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


Re: try..except with empty exceptions

2015-04-11 Thread Ian Foote
-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

On 11/04/15 08:11, Steven D'Aprano wrote:
 But with try...except, an empty exception list means to catch
 *everything*, not nothing:
 
 try: ... except a,b,c: # catches a, b, c
 
 try: ... except a,b: # catches a, b

This example is incorrect. In python3 it is a SyntaxError:

Python 3.4.0 (default, Apr 11 2014, 13:05:11)
[GCC 4.8.2] on linux
Type help, copyright, credits or license for more
information.
 try:
...  1/0
... except ValueError, ZeroDivisionError:
  File stdin, line 3
except ValueError, ZeroDivisionError:
 ^
SyntaxError: invalid syntax

In python2 it aliases ValueError as ZeroDivisionError:

Python 2.7.6 (default, Mar 22 2014, 22:59:56)
[GCC 4.8.2] on linux2
Type help, copyright, credits or license for more
information.
 try:
...  1/0
... except ValueError, ZeroDivisionError:
...  pass
...
Traceback (most recent call last):
  File stdin, line 2, in module
ZeroDivisionError: integer division or modulo by zero

To get the behaviour you expect, you must use parentheses:

 try:
...  1/0
... except (ValueError, ZeroDivisionError):
...  pass
...

Regards,
Ian F
-BEGIN PGP SIGNATURE-
Version: GnuPG v1

iQEcBAEBAgAGBQJVKS2dAAoJEODsV4MF7PWznkAH/jidWhoJ//gsvBr0ByOOOEgc
A+k8HqrkALfzrh3aEjJB3sq19oLfLcepQeFVUh77mJKOMCQdEeyJtqIz6tLc4RUa
L/nXytHygXVTb5HIARGVkPD26gqAleSb9eZUfPeSEvRHy9UbFS7SMmOdkApheDX3
Vq8TOa8EchaYd+S89y9eepZAhGC7n2TNwrNgp36sbHoz/hYUxFNnugP0ow9FM0Wk
MGKGh04c3Lao+6w7a0scz4YKKb8wTdYkyYwlJhEdg3q74+PwYJpkjcGucna745AZ
XlAKlDCJ9LhPgMufuGdRNskJa4TF709ec5hG9itHu1lFKrjH1iJCEU9ntX6hInU=
=zi4K
-END PGP SIGNATURE-
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: try..except with empty exceptions

2015-04-11 Thread Dave Angel

On 04/11/2015 06:14 AM, Dave Angel wrote:

On 04/11/2015 03:11 AM, Steven D'Aprano wrote:

On Sat, 11 Apr 2015 12:23 pm, Dave Angel wrote:


On 04/10/2015 09:42 PM, Steven D'Aprano wrote:

On Sat, 11 Apr 2015 05:31 am, sohcahto...@gmail.com wrote:


It isn't document because it is expected.  Why would the exception get
caught if you're not writing code to catch it?  If you write a
function
and pass it a tuple of exceptions to catch, I'm not sure why you would
expect it to catch an exception not in the tuple.  Just because the
tuple
is empty doesn't mean that it should catch *everything* instead.  That
would be counter-intuitive.


Really? I have to say, I expected it.




I'm astounded at your expectation.  That's like saying a for loop on an
empty list ought to loop on all possible objects in the universe.


Not really.

If we wrote:

 for x in:
 # Missing sequence leads to an infinite loop

*then* your analogy would be excellent, but it isn't. With for loops, we
iterate over each item in the sequence, hence an empty sequence means we
don't iterate at all.

But with try...except, an empty exception list means to catch
*everything*,
not nothing:


No an empty exception list means to catch nothing.  A *missing*
exception list means catch everything, but that's a different syntax


try: ...
except a,b,c: # catches a, b, c

try: ...
except a,b: # catches a, b

try: ...
except a: # catches a


try: ...
except (a,)   #catches a

try: ...
except ()  #catches nothing, as expected



try: ...
except: # catches EVERYTHING, not nothing



Different syntax.  No reason for it to pretend that it's being given an
empty tuple or list.



Putting (a, b, c) into a tuple shouldn't make a difference, and it
doesn't,
unless the tuple is empty. That surprised me.

t = a, b, c
try:
except t:  # same as except a,b,c

t = a, b
try:
except t:  # same as except a,b

t = a,
try:
except t:  # same as except a

t = ()
try:
except t:  # NOT THE SAME as bare except.


Of course not.  It's empty, so it catches nothing. Just like 'for'




I can see the logic behind the current behaviour. If you implement except
clauses like this pseudo-code:


for exc in exceptions:
 if raised_exception matches exc: catch it


then an empty tuple will naturally lead to nothing being caught. That
doesn't mean it isn't surprising from the perspective that an empty
exception list (i.e. a bare except) should be analogous to an empty
tuple.


Why should it??  It's a different syntax, with different rules.  Perhaps
it should have been consistent, but then it's this statement that's
surprising, not the behavior with an empty tuple.





The tuple lists those exceptions you're interested in, and they are
tried, presumably in order, from that collection.  If none of those
match, then the logic will advance to the next except clause.  If the
tuple is empty, then clearly none will match.


Yes, that makes sense, and I agree that it is reasonable behaviour
from one
perspective. But its also reasonable to treat except (): as
analogous to
a bare except.

[...]

try:
  spam()
except:
  # Implicitly an empty tuple.


No, an omitted item is not the same as an empty tuple.


You are correct about Python as it actually is, but it could have been
designed so that except (): was equivalent to a bare except.


Only by changing the bare except behavior.





If it were, then
we wouldn't have the problem of bare excepts, which are so tempting to
novices.  There's plenty of precedent in many languages for a missing
item being distinct from anything one could actually supply.


Let us put aside the fact that some people misuse bare excepts, and allow
that there are some uses for it. Now, in Python 2.6 and later, you can
catch everything by catching BaseException. But in older versions, you
could raise strings as well, and the only way to catch everything is
with a
bare except.

If you want to write a function that takes a list of things to catch,
defaulting to everything, in Python 2.6+ we can write:

def spam(things_to_catch=BaseException):
 try:
 do_stuff()
 except things_to_catch:
 handle_exception()


but in older versions you have to write this:

def spam(things_to_catch=None):
 if things_to_catch is None:
 try:
 do_stuff()
 except:
 handle_exception()
 else:
 try:
 do_stuff()
 except things_to_catch:
 handle_exception()


This violates Don't Repeat Yourself. Any time you have a missing item
being
distinct from anything one could actually supply, you have a poor
design.


Yep, and it happens all the time.  For example, mylist[a,b,-1]What
value can I use for b to mean the whole list?

There are others more grotesque, but I can't think of any at this moment.



Anyway, in modern Python (2.6 onwards), now that string exceptions are
gone,
you can supply something to catch everything. Or nothing, for that
matter:

BaseException  # catch 

Re: try..except with empty exceptions

2015-04-11 Thread Steven D'Aprano
On Sat, 11 Apr 2015 07:27 pm, Cameron Simpson wrote:

 If the empty tuple were to mean catch everything then there would not be
 a way to express catch nothing. Bad bad bad!

# Catch everything:
try:
spam()
except:
pass


# Catch nothing:
spam()


:-)


 Consider this a proof that Python's current meanings for bare except and
 except () are sensible, using a proof by contradiction.


Given that Python 3 does not allow you to raise things which don't inherit
from BaseException, I wish that bare except clauses were dropped
altogether. In Python 3, the equivalent to catch everything is
spelled except BaseException, which I think would be a lot less
attractive to beginners than bare except:.

But I digress.

Yes, I agree that Python's behaviour here is better than the alternative.
Having except () catch nothing is consistent with the behaviour with
other tuples, so I'm okay with that. But it still surprised me :-)



-- 
Steven

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


Re: try..except with empty exceptions

2015-04-11 Thread Chris Angelico
On Sat, Apr 11, 2015 at 9:00 PM, Steven D'Aprano
steve+comp.lang.pyt...@pearwood.info wrote:
 Yes, I agree that Python's behaviour here is better than the alternative.
 Having except () catch nothing is consistent with the behaviour with
 other tuples, so I'm okay with that. But it still surprised me :-)

It's worth noting that there's another false parallel here. Grouping
nothing creates something.

x = 1   # x is an integer
x = (1)  # ditto
x = (1)  # LITHP

Okay, so adding parentheses does nothing, right? Right.

x =  # syntax error
x = ()  # empty tuple

Parentheses around nothing is NOT the same as nothing. So if you
compare against this, then it makes perfect sense for except : and
except (): to be distinctly different.

But I agree, it would be very nice if Python 3 could have abolished
the truly confusing part of this, where except: catches everything.
Forcing people to spell it except BaseException: would fix all of
this. How hard is it to deprecate and then remove that, same as string
exceptions were removed?

You know what, I'm moving that to -ideas.

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


Re: try..except with empty exceptions

2015-04-11 Thread Cameron Simpson

On 12Apr2015 07:52, Chris Angelico ros...@gmail.com wrote:

On Sun, Apr 12, 2015 at 7:37 AM, Cameron Simpson c...@zip.com.au wrote:

On 11Apr2015 21:21, Chris Angelico ros...@gmail.com wrote:

But I agree, it would be very nice if Python 3 could have abolished
the truly confusing part of this, where except: catches everything.
Forcing people to spell it except BaseException: would fix all of
this. How hard is it to deprecate and then remove that, same as string
exceptions were removed?


I guess I'll go over there to oppose it then.

Why? It makes it harder to write portable python 2/3 code and does not add
any semantic advantage.

Unless there's a common root exception class in Python 2, which I believe
there isn't, you can't catch all exceptions in python 2 without the
except: syntax.  Which means the _only_ way to have some code in both 2
and 3 that does it requires 2 codebases.

As one who tries to have his code run in both 2 (usually recent 2, like
2.6/2.7) and 3, this change would cause a signification breakage for me
without bringing any semantic benefits.


Can you give an example of a place where in Py2 you absolutely have to
catch everything, and don't have control over the code, *and* are
trying to do a one-codebase routine with Py3 compatibility? If you're
trying for 2/3 compatibility, you'll need to have all your exceptions
derive from BaseException anyway.


I don't make many personal exception classes, tending to reuse stdlib ones. I'm 
sure I have a few.


But regarding codebase:

   [hg/css]fleet* g except: **/*.py
   lib/python/cs/app/pilfer.py:664:  except:
   lib/python/cs/asynchron.py:145:except:
   lib/python/cs/db.py:184:  except:
   lib/python/cs/excutils.py:34:  except:
   lib/python/cs/fileutils.py:69:  except:
   lib/python/cs/idset.py:46:  except:
   lib/python/cs/later.py:156:except:
   lib/python/cs/mailutils.py:274:  except:
   lib/python/cs/nodedb/tokcab.py:57:except:
   lib/python/cs/queues.py:441:  except:
   lib/python/cs/queues.py:458:  except:
   lib/python/cs/threads.py:131:  except:

Catching all exceptions isn't terribly common, _except_ in service routines 
that wrap unknown operations. Classic example from my Asynchron class:


   def call(self, func, *a, **kw):
 ''' Have the Asynchron call `func(*a,**kw)` and store its values as
 self.result.
 If `func` raises an exception, store it as self.exc_info.
 '''
 try:
   r = func(*a, **kw)
 except:
   self.exc_info = sys.exc_info
 else:
   self.result = r

All sorts of things like thread pools and other worker functions, and 
run-forever daemons like mail filers that can have arbitrary exceptions occur 
in (partly) third party code eg from config files; you need to catch any 
unknown exception and fail the specific action, but continue the main daemon 
operation.


And since I use this code in Python 2, and since not all exceptions are 
BaseException subclasses, I need the bare syntax.


Also, IMO, a bare except: syntax is _far_ more pleasing to the eye than 
except magic_exception_name_that+gets_everything:. Also, I wish 
BaseException were just spelled Exception, if it has to be used.



At very worst, it could be turned into a compat-only syntax feature,
like the uspam noise prefix on Unicode strings - serving absolutely
no purpose in Py3 code, and ideally, able to be removed at some point
post-2020.


I'm -0.1 on the idea myself. I consider except: succinct and evocative, and 
prefer it to except BaseException:.


Cheers,
Cameron Simpson c...@zip.com.au

On a videophone, the whole world can see you fart.  - Charlie Stross
--
https://mail.python.org/mailman/listinfo/python-list


Re: try..except with empty exceptions

2015-04-11 Thread Chris Angelico
On Sun, Apr 12, 2015 at 9:08 AM, Cameron Simpson c...@zip.com.au wrote:
 Catching all exceptions isn't terribly common, _except_ in service routines
 that wrap unknown operations. Classic example from my Asynchron class:

def call(self, func, *a, **kw):
  ''' Have the Asynchron call `func(*a,**kw)` and store its values as
  self.result.
  If `func` raises an exception, store it as self.exc_info.
  '''
  try:
r = func(*a, **kw)
  except:
self.exc_info = sys.exc_info
  else:
self.result = r

 All sorts of things like thread pools and other worker functions, and
 run-forever daemons like mail filers that can have arbitrary exceptions
 occur in (partly) third party code eg from config files; you need to catch
 any unknown exception and fail the specific action, but continue the main
 daemon operation.

 And since I use this code in Python 2, and since not all exceptions are
 BaseException subclasses, I need the bare syntax.

Fair enough. Do you know how often you actually catch stuff that
wouldn't be caught by except BaseException:? I would guess it's
pretty rare. In fact, you can find out.

 try:
   r = func(*a, **kw)
 except BaseException:
   self.exc_info = sys.exc_info
 except:
   self.exc_info = sys.exc_info
   emit_warning()
else:
   self.result = r

You could simply mandate that, from version X.Y of your Asynchron
module onward, old-style classes must not be thrown.

 Also, IMO, a bare except: syntax is _far_ more pleasing to the eye than
 except magic_exception_name_that+gets_everything:. Also, I wish
 BaseException were just spelled Exception, if it has to be used.

 I'm -0.1 on the idea myself. I consider except: succinct and evocative,
 and prefer it to except BaseException:.

What you're looking at here is exactly why it's not spelled that way.
The normal thing to do is NOT to catch absolutely everything, but to
allow KeyboardInterrupt and SystemExit to continue to bubble up.
That's spelled except Exception. My whole point here is that the
bare except catches too much for normal use, and therefore should
_not_ be pleasing to the eye. The thing you should most often be doing
is except ValueError or equivalent; forcing you to put at least
_some_ name into the exception clause emphasizes that being specific
is not the unusual case.

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


Re: try..except with empty exceptions

2015-04-10 Thread Rustom Mody
On Saturday, April 11, 2015 at 9:47:36 AM UTC+5:30, Rustom Mody wrote:
 On Saturday, April 11, 2015 at 9:17:16 AM UTC+5:30, Dave Angel wrote:
  On 04/10/2015 10:38 PM, Rustom Mody wrote:
   On Saturday, April 11, 2015 at 7:53:31 AM UTC+5:30, Dave Angel wrote:
   On 04/10/2015 09:42 PM, Steven D'Aprano wrote:
   On Sat, 11 Apr 2015 05:31 am, sohcahtoa82 wrote:
  
   It isn't document because it is expected.  Why would the exception get
   caught if you're not writing code to catch it?  If you write a function
   and pass it a tuple of exceptions to catch, I'm not sure why you would
   expect it to catch an exception not in the tuple.  Just because the 
   tuple
   is empty doesn't mean that it should catch *everything* instead.  That
   would be counter-intuitive.
  
   Really? I have to say, I expected it.
  
  
  
   I'm astounded at your expectation.  That's like saying a for loop on an
   empty list ought to loop on all possible objects in the universe.
  
   To work, this analogy should also have two python syntaxes like this:
  
   Normal for-loop:
   for var in iterable:
  suite
  
   Empty for-loop:
   for:
  suite
  
  
  That tells me nothing about your opinions.  What did you mean by the 
  phrase to work?
 
 Your analogy is for loop on an empty list ought to loop on all possible
 objects in the universe
 This seemingly works as a demo of a ridiculous expectation
 because there is only one pattern of for-loop
 for var in iterable:
 
 In the case of exceptions we have two patterns
 except e-tuple:
 and
 except: 
 with the second having a wildly different semantics from the first

IOW:
OP is surprised that except (): is a no-op
The real surprise is that except: is valid syntax with questionable semantics
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: try..except with empty exceptions

2015-04-10 Thread Dave Angel

On 04/10/2015 10:38 PM, Rustom Mody wrote:

On Saturday, April 11, 2015 at 7:53:31 AM UTC+5:30, Dave Angel wrote:

On 04/10/2015 09:42 PM, Steven D'Aprano wrote:

On Sat, 11 Apr 2015 05:31 am, sohcahtoa82 wrote:


It isn't document because it is expected.  Why would the exception get
caught if you're not writing code to catch it?  If you write a function
and pass it a tuple of exceptions to catch, I'm not sure why you would
expect it to catch an exception not in the tuple.  Just because the tuple
is empty doesn't mean that it should catch *everything* instead.  That
would be counter-intuitive.


Really? I have to say, I expected it.




I'm astounded at your expectation.  That's like saying a for loop on an
empty list ought to loop on all possible objects in the universe.


To work, this analogy should also have two python syntaxes like this:

Normal for-loop:
for var in iterable:
   suite

Empty for-loop:
for:
   suite



That tells me nothing about your opinions.  What did you mean by the 
phrase to work?  My analogy already works.  The for loop on an empty 
list loops zero times.  Just like try/except on an empty tuple catches 
zero exception types.


As for the separate syntax, that might be an acceptable extension to 
Python.  But it already has a convention for an infinite loop, which is

 while True:
I'm pretty sure do{} works as an infinite loop in C, but perhaps I'm 
remembering some other language where you could omit the conditional.






--
DaveA
--
https://mail.python.org/mailman/listinfo/python-list


Re: try..except with empty exceptions

2015-04-10 Thread Rustom Mody
On Saturday, April 11, 2015 at 9:17:16 AM UTC+5:30, Dave Angel wrote:
 On 04/10/2015 10:38 PM, Rustom Mody wrote:
  On Saturday, April 11, 2015 at 7:53:31 AM UTC+5:30, Dave Angel wrote:
  On 04/10/2015 09:42 PM, Steven D'Aprano wrote:
  On Sat, 11 Apr 2015 05:31 am, sohcahtoa82 wrote:
 
  It isn't document because it is expected.  Why would the exception get
  caught if you're not writing code to catch it?  If you write a function
  and pass it a tuple of exceptions to catch, I'm not sure why you would
  expect it to catch an exception not in the tuple.  Just because the tuple
  is empty doesn't mean that it should catch *everything* instead.  That
  would be counter-intuitive.
 
  Really? I have to say, I expected it.
 
 
 
  I'm astounded at your expectation.  That's like saying a for loop on an
  empty list ought to loop on all possible objects in the universe.
 
  To work, this analogy should also have two python syntaxes like this:
 
  Normal for-loop:
  for var in iterable:
 suite
 
  Empty for-loop:
  for:
 suite
 
 
 That tells me nothing about your opinions.  What did you mean by the 
 phrase to work?

Your analogy is for loop on an empty list ought to loop on all possible
objects in the universe
This seemingly works as a demo of a ridiculous expectation
because there is only one pattern of for-loop
for var in iterable:

In the case of exceptions we have two patterns
except e-tuple:
and
except: 
with the second having a wildly different semantics from the first
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: try..except with empty exceptions

2015-04-10 Thread Dave Angel

On 04/10/2015 04:48 AM, Pavel S wrote:

Hi,

I noticed interesting behaviour. Since I don't have python3 installation here, 
I tested that on Python 2.7.

Well known feature is that try..except block can catch multiple exceptions 
listed in a tuple:


exceptions = ( TypeError, ValueError )

try:
 a, b = None
except exceptions, e:
 print 'Catched error:', e


However when exceptions=(), then try..except block behaves as no try..except 
block.


exceptions = ()

try:
 a, b = None   # --- the error will not be catched
except exceptions, e:
 print 'Catched error:', e


I found use case for it, e.g. when I want to have a method with 'exceptions' 
argument:


def catch_exceptions(exceptions=()):
   try:
  do_something()
   except exceptions:
  do_something_else()


catch_exceptions()   # catches nothing
catch_exceptions((TypeError,))   # catches TypeError


I believe that behaviour is not documented. What you think?



It's no more surprising than a for loop over an empty tuple or empty 
list.  There's nothing to do, so you do nothing.




--
DaveA
--
https://mail.python.org/mailman/listinfo/python-list


Re: try..except with empty exceptions

2015-04-10 Thread Steven D'Aprano
On Sat, 11 Apr 2015 05:31 am, sohcahto...@gmail.com wrote:

 It isn't document because it is expected.  Why would the exception get
 caught if you're not writing code to catch it?  If you write a function
 and pass it a tuple of exceptions to catch, I'm not sure why you would
 expect it to catch an exception not in the tuple.  Just because the tuple
 is empty doesn't mean that it should catch *everything* instead.  That
 would be counter-intuitive.

Really? I have to say, I expected it.


try:
spam()
except This, That:
# Implicitly a tuple of two exceptions.
pass


Compare:

try:
spam()
except:
# Implicitly an empty tuple.
pass


I'm not surprised that it fails, especially in Python 2 before
the except ... as err syntax was available, but the OP is not alone in
thinking that an empty tuple should catch everything.


I'm fairly dubious about catching everything, that sounds like a good way to
hide bugs, but if you need to catch everything, using Exception is the
usual way to do it.




-- 
Steven

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


Re: try..except with empty exceptions

2015-04-10 Thread Rustom Mody
On Friday, April 10, 2015 at 2:18:22 PM UTC+5:30, Pavel S wrote:
 Hi,
 
 I noticed interesting behaviour. Since I don't have python3 installation 
 here, I tested that on Python 2.7.
 
 Well known feature is that try..except block can catch multiple exceptions 
 listed in a tuple:
 
 
 exceptions = ( TypeError, ValueError )
 
 try:
 a, b = None
 except exceptions, e:
 print 'Catched error:', e
 
 
 However when exceptions=(), then try..except block behaves as no try..except 
 block.
 
 
 exceptions = ()
 
 try:
 a, b = None   # --- the error will not be catched
 except exceptions, e:
 print 'Catched error:', e
 
 
 I found use case for it, e.g. when I want to have a method with 'exceptions' 
 argument:
 
 
 def catch_exceptions(exceptions=()):
   try:
  do_something()
   except exceptions:
  do_something_else()
 
 
 catch_exceptions()   # catches nothing
 catch_exceptions((TypeError,))   # catches TypeError
 
 
 I believe that behaviour is not documented. What you think?

As others have pointed out: You asked for it; you got it; what's the issue?

Nevertheless a tentative +1 from me on the suggestions ∵

except :

catches everything 

except ():

catches nothing --- which is brittle to say the least.

Also given this sort of lines in the docs (2.7 tutorial):

-
... except (RuntimeError, TypeError, NameError):
... pass

Note that the parentheses around this tuple are required, because except
ValueError, e: was the syntax used for what is normally written as except
ValueError as e: in modern Python (described below). The old syntax is still 
supported for backwards compatibility. This means except RuntimeError, 
TypeError is not equivalent to except (RuntimeError, TypeError): but to except 
RuntimeError as TypeError: which is not what you want.


there's already some versioning related brittleness around except.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: try..except with empty exceptions

2015-04-10 Thread Dave Angel

On 04/10/2015 09:42 PM, Steven D'Aprano wrote:

On Sat, 11 Apr 2015 05:31 am, sohcahto...@gmail.com wrote:


It isn't document because it is expected.  Why would the exception get
caught if you're not writing code to catch it?  If you write a function
and pass it a tuple of exceptions to catch, I'm not sure why you would
expect it to catch an exception not in the tuple.  Just because the tuple
is empty doesn't mean that it should catch *everything* instead.  That
would be counter-intuitive.


Really? I have to say, I expected it.




I'm astounded at your expectation.  That's like saying a for loop on an 
empty list ought to loop on all possible objects in the universe.


The tuple lists those exceptions you're interested in, and they are 
tried, presumably in order, from that collection.  If none of those 
match, then the logic will advance to the next except clause.  If the 
tuple is empty, then clearly none will match.



try:
 spam()
except This, That:
 # Implicitly a tuple of two exceptions.
 pass


Compare:

try:
 spam()
except:
 # Implicitly an empty tuple.


No, an omitted item is not the same as an empty tuple.  If it were, then 
we wouldn't have the problem of bare excepts, which are so tempting to 
novices.  There's plenty of precedent in many languages for a missing 
item being distinct from anything one could actually supply.


When there's no tuple specified, it's a different syntax, and the 
semantics are specified separately.




--
DaveA
--
https://mail.python.org/mailman/listinfo/python-list


Re: try..except with empty exceptions

2015-04-10 Thread Rustom Mody
On Saturday, April 11, 2015 at 7:53:31 AM UTC+5:30, Dave Angel wrote:
 On 04/10/2015 09:42 PM, Steven D'Aprano wrote:
  On Sat, 11 Apr 2015 05:31 am, sohcahtoa82 wrote:
 
  It isn't document because it is expected.  Why would the exception get
  caught if you're not writing code to catch it?  If you write a function
  and pass it a tuple of exceptions to catch, I'm not sure why you would
  expect it to catch an exception not in the tuple.  Just because the tuple
  is empty doesn't mean that it should catch *everything* instead.  That
  would be counter-intuitive.
 
  Really? I have to say, I expected it.
 
 
 
 I'm astounded at your expectation.  That's like saying a for loop on an 
 empty list ought to loop on all possible objects in the universe.

To work, this analogy should also have two python syntaxes like this:

Normal for-loop:
for var in iterable:
  suite

Empty for-loop:
for:
  suite

[Sorry Steven… didn't notice you were agreeing with me…
a rare privilege 
]
-- 
https://mail.python.org/mailman/listinfo/python-list