Re: try-except with no exceptions
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
Daiyue Wengwrites: > 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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
-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
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
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
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
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
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
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
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
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
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
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
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
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
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