Path: csiph.com!usenet.pasdenom.info!weretis.net!feeder1.news.weretis.net!feeder.erje.net!eu.feeder.erje.net!newsfeed.xs4all.nl!newsfeed4a.news.xs4all.nl!xs4all!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.001 X-Spam-Evidence: '*H*': 1.00; '*S*': 0.00; 'subject:Python': 0.06; 'context': 0.07; 'finally:': 0.07; 'exception,': 0.09; 'exception.': 0.09; 'indicates': 0.09; 'raises': 0.09; 'try:': 0.09; 'valueerror:': 0.09; 'variant': 0.09; 'python': 0.11; 'jan': 0.12; '(note': 0.16; 'chained': 0.16; 'exception:': 0.16; 'handled.': 0.16; 'merely': 0.16; 'raised,': 0.16; 'retains': 0.16; 'throw': 0.16; 'unexpected': 0.16; 'valueerror': 0.16; 'valueerror,': 0.16; 'exception': 0.16; 'followed': 0.16; 'wrote:': 0.18; 'bit': 0.19; 'pieces': 0.19; 'separate': 0.22; 'error': 0.23; 'changes,': 0.26; 'first,': 0.26; 'handling': 0.26; 'primary': 0.26; 'header:In-Reply-To:1': 0.27; 'am,': 0.29; 'raise': 0.29; "doesn't": 0.30; 'message-id:@mail.gmail.com': 0.30; "i'm": 0.30; 'code': 0.31; 'lines': 0.31; '"",': 0.31; '>>>>': 0.31; 'apparently': 0.31; 'bug?': 0.31; 'equivalent.': 0.31; 'exceptions': 0.31; 'raised': 0.31; 'file': 0.32; 'another': 0.32; '(most': 0.33; 'fri,': 0.33; 'skip:d 20': 0.34; 'could': 0.34; 'problem': 0.35; 'except': 0.35; 'but': 0.35; 'received:google.com': 0.35; 'object,': 0.36; 'two': 0.37; 'being': 0.38; 'to:addr:python-list': 0.38; 'recent': 0.39; 'expect': 0.39; 'to:addr:python.org': 0.39; 'enough': 0.39; 'chain': 0.60; 'most': 0.60; 'break': 0.61; 'information': 0.63; 'happen': 0.63; 'subject:The': 0.64; '30,': 0.65; 'kept': 0.65; 'here': 0.66; '2015': 0.84; '3:00': 0.84; 'bare': 0.84; 'surface': 0.84; 'whereas': 0.91 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :content-type; bh=lQrTNftPPP5NJK9/r1MMycjaUH1caRO7hEMa+oVQExc=; b=icEBQTXp9Itkm8r5rBfG9LNUQmk7oMvzqnUo1NgTv1trVKzQvPtgitw2noQybEzsrR 8T2BD7Q+XS2MStKhYWYRwfC3/1SkpaXfnUyCS6SnMv7G92Bil2tNRvQJj9NJtvtz5ni2 BhuHWpp2u3hfuJ1+yhVIDu4pjbcrzoXK7YUWfCcVgQQaxT9A5OgneEehmYQwZQQArq8v pIOYjaJ+P4qcj6iMCHl9TzLLIn98/77rOhhjTp7Mg65qeP3evwzunW75emEIuQQpWILJ 0hGdgmA7qt+2wtosF4YBqYPK9343ouq+8taXQQU0746TG6EXlAml+6HZDhXDl2dBL3SP Z4nQ== X-Received: by 10.66.234.40 with SMTP id ub8mr9812813pac.122.1422631310124; Fri, 30 Jan 2015 07:21:50 -0800 (PST) MIME-Version: 1.0 In-Reply-To: <87fvaslh9h.fsf@elektro.pacujo.net> References: <20150129113238.7eaa986d@bigbox.christie.dr> <87r3uchjyg.fsf@elektro.pacujo.net> <87r3ucljyv.fsf@elektro.pacujo.net> <87fvaslh9h.fsf@elektro.pacujo.net> From: Ian Kelly Date: Fri, 30 Jan 2015 08:21:09 -0700 Subject: Re: The Most Diabolical Python Antipattern To: Python Content-Type: text/plain; charset=UTF-8 X-BeenThere: python-list@python.org X-Mailman-Version: 2.1.15 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: 67 NNTP-Posting-Host: 2001:888:2000:d::a6 X-Trace: 1422631319 news.xs4all.nl 2849 [2001:888:2000:d::a6]:57749 X-Complaints-To: abuse@xs4all.nl Xref: csiph.com comp.lang.python:84891 On Fri, Jan 30, 2015 at 3:00 AM, Marko Rauhamaa wrote: > Marko Rauhamaa : > >>>> Surprisingly this variant could raise an unexpected exception: >>>> >>>> ============================== >>>> try: >>>> do_interesting_stuff() >>>> except ValueError: >>>> try: >>>> log_it() >>>> finally: >>>> raise >>>> ============================== >>>> >>>> A Python bug? >> [...] >> My Python did do exception chaining, but the problem is the surface >> exception changes, which could throw off the whole error recovery. > > BTW, the code above can be fixed: > > ============================== > try: > do_interesting_stuff() > except ValueError as e: > try: > log_it() > finally: > raise e > ============================== > > Now the surface exception is kept and the subsidiary exception is > chained to it. > > I'm a bit baffled why the two pieces of code are not equivalent. The bare raise re-raises the most recent exception that is being handled. The "raise e" raises that exception specifically, which is not the most recent in the case of a secondary exception. Note that the exceptions are actually chained *in reverse*; the message falsely indicates that the secondary exception was raised first, and the primary exception was raised while handling it, e.g.: Traceback (most recent call last): File "", line 5, in TypeError During handling of the above exception, another exception occurred: Traceback (most recent call last): File "", line 7, in File "", line 2, in ValueError That's because "raise e" causes the exception e to be freshly raised, whereas the bare "raise" merely makes the existing exception context active again. It's interesting to note here that although the exception retains its original traceback information (note the two separate lines in the traceback), it is not chained again from the TypeError. One might expect to actually see the ValueError, followed by the TypeError, followed by the ValueError in the chain. That doesn't happen because the two ValueErrors raised are actually the same object, and Python is apparently wise enough to break the chain to avoid an infinite cycle.