Path: csiph.com!usenet.pasdenom.info!news.redatomik.org!newsfeed.xs4all.nl!newsfeed1.news.xs4all.nl!xs4all!newsgate.cistron.nl!newsgate.news.xs4all.nl!post.news.xs4all.nl!not-for-mail Return-Path: X-Original-To: python-list@python.org Delivered-To: python-list@mail.python.org X-Spam-Status: OK 0.000 X-Spam-Evidence: '*H*': 1.00; '*S*': 0.00; 'else:': 0.03; 'syntax': 0.04; 'say,': 0.05; 'list?': 0.07; 'matches': 0.07; 'none:': 0.07; 'plenty': 0.07; 'suppose': 0.07; 'versions,': 0.07; 'advance': 0.07; 'string': 0.09; 'difference,': 0.09; 'except:': 0.09; 'expected.': 0.09; 'iterate': 0.09; 'logic': 0.09; 'naturally': 0.09; 'pretend': 0.09; 'try:': 0.09; 'violates': 0.09; 'python': 0.11; 'def': 0.12; "wouldn't": 0.14; 'behaviour.': 0.16; 'clause.': 0.16; 'clauses': 0.16; 'defaulting': 0.16; 'distinct': 0.16; 'empty,': 0.16; 'empty.': 0.16; 'excellent,': 0.16; 'ought': 0.16; 'really?': 0.16; 'rules.': 0.16; 'sense,': 0.16; 'sequence,': 0.16; 'subclasses': 0.16; 'surprising': 0.16; 'syntax,': 0.16; 'tuple': 0.16; 'tuple.': 0.16; 'exception': 0.16; 'sat,': 0.16; 'all.': 0.16; 'wrote:': 0.18; 'items.': 0.19; '>>>': 0.22; 'putting': 0.22; 'saying': 0.22; 'header:User-Agent:1': 0.23; 'instead.': 0.24; 'logical': 0.24; "shouldn't": 0.24; 'versions': 0.24; '(or': 0.24; 'equivalent': 0.26; 'this:': 0.26; 'pass': 0.26; 'header:In-Reply-To:1': 0.27; 'function': 0.29; 'correct': 0.29; 'am,': 0.29; 'raise': 0.29; "doesn't": 0.30; 'errors': 0.30; 'statement': 0.30; "i'm": 0.30; 'code': 0.31; '>>>>': 0.31; 'catching': 0.31; "d'aprano": 0.31; 'exceptions': 0.31; 'omitted': 0.31; 'steven': 0.31; 'yourself.': 0.31; 'lists': 0.32; 'languages': 0.32; '(i.e.': 0.33; 'not.': 0.33; 'older': 0.33; 'could': 0.34; 'problem': 0.35; 'subject:with': 0.35; "can't": 0.35; 'agree': 0.35; 'except': 0.35; 'skip:s 30': 0.35; 'something': 0.35; 'no,': 0.35; 'objects': 0.35; 'but': 0.35; 'there': 0.35; '2.6': 0.36; 'in:': 0.36; 'leads': 0.36; 'sequence': 0.36; 'next': 0.36; 'possible': 0.36; 'should': 0.36; 'behind': 0.37; 'changing': 0.37; 'example,': 0.37; 'list': 0.37; 'list.': 0.37; 'being': 0.38; 'expected': 0.38; 'implement': 0.38; 'to:addr:python-list': 0.38; 'fact': 0.38; 'pm,': 0.38; 'anything': 0.39; 'expect': 0.39; 'aside': 0.39; 'sure': 0.39; 'to:addr:python.org': 0.39; 'catch': 0.60; 'dave': 0.60; 'skip:* 10': 0.61; 'course': 0.61; "you're": 0.61; 'email addr:gmail.com': 0.63; 'more': 0.64; 'different': 0.65; 'charset:windows-1252': 0.65; 'design.': 0.68; 'received:74.208': 0.68; 'repeat': 0.74; 'behavior': 0.77; "'for'": 0.84; '2015': 0.84; 'bare': 0.84; 'collection.': 0.84; 'everything,': 0.84; 'everything.': 0.84; 'perspective.': 0.84; 'presumably': 0.84; 'subject:..': 0.84; 'angel': 0.91; 'items,': 0.91; 'write:': 0.91 Date: Sat, 11 Apr 2015 06:14:24 -0400 From: Dave Angel User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.5.0 MIME-Version: 1.0 To: python-list@python.org Subject: Re: try..except with empty exceptions References: <64a75c32-e0ab-4ce0-9373-358c2669fe6e@googlegroups.com> <785010c0-6bcc-46d7-b7e0-0ed062fabbc7@googlegroups.com> <55287c0d$0$13000$c3e8da3$5496439d@news.astraweb.com> <5528c906$0$12994$c3e8da3$5496439d@news.astraweb.com> In-Reply-To: <5528c906$0$12994$c3e8da3$5496439d@news.astraweb.com> Content-Type: text/plain; charset=windows-1252; format=flowed Content-Transfer-Encoding: 7bit X-Provags-ID: V03:K0:hiI7Skq/n+2NpYtercvhVuEPfc923RnF+K4MxWZ9CtlUEr8WmNf dPU7fjfdLozzpgyuYoq8eeSYr1nndN6EzQSkvpo5SQWexc4nDAHE56P15gcPuN3GCJclbH7 Fl26KagZ31RwD59SZFKGJ7jghELFYHjbJHrxPROHbXGtgHjVY5LaKUFBbzOH2qMDi33mIEc j7SRFkfGwxvmfLnSXNrJw== X-UI-Out-Filterresults: notjunk:1; X-BeenThere: python-list@python.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: General discussion list for the Python programming language List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Newsgroups: comp.lang.python Message-ID: Lines: 192 NNTP-Posting-Host: 2001:888:2000:d::a6 X-Trace: 1428747278 news.xs4all.nl 2916 [2001:888:2000:d::a6]:43892 X-Complaints-To: abuse@xs4all.nl Xref: csiph.com comp.lang.python:88814 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, sohcahtoa82@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 > (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. > Just like with all(()) and any(()), there's a logical way and an illogical way. An empty list means no items, not all possible items. -- DaveA