classification
Title: [doc] Scope for raise without argument is different in Python 2 and 3
Type: behavior Stage: patch review
Components: Documentation, Interpreter Core Versions: Python 3.11, Python 3.10, Python 3.9
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: docs@python Nosy List: SilentGhost, a3nm, collinwinter, docs@python, iritkatriel, jayvdb, kinshukdua, martin.panter
Priority: normal Keywords: easy, patch

Created on 2015-03-01 12:14 by a3nm, last changed 2021-10-27 13:10 by kinshukdua.

Files
File name Uploaded Description Edit
raise.py a3nm, 2015-03-01 12:14 Minimal example
raise-scope-py3.patch martin.panter, 2015-07-29 09:28 For Python 3 review
Pull Requests
URL Status Linked Edit
PR 29236 open kinshukdua, 2021-10-27 13:10
Messages (6)
msg236957 - (view) Author: Antoine Amarilli (a3nm) Date: 2015-03-01 12:14
Hello,

Python 2.7.8 and Python 3.4.2 (from Debian testing) have a different behavior on the attached file. Python 2 raises "bar", Python 3 raises "foo".

I can't find an adequate explanation in the documentation for this behavior difference. It probably relates to https://docs.python.org/3/reference/compound_stmts.html#try (search for "When an exception has been assigned") but this is unsatisfying because it only talks about the "as target" construction, which is not used in the example.

I think that at least the documentation should be clarified to point out what "raise" without arguments will do. Currently the documentation of this in Python 2 and 3 is the same even though the behavior is different https://docs.python.org/2/reference/simple_stmts.html#raise https://docs.python.org/3/reference/simple_stmts.html#raise.

Note: this question was originally asked on SO: http://stackoverflow.com/q/28698622/414272. I reported this as a bug at Terry Jan Reedy's request https://stackoverflow.com/q/28698622/414272#comment45707744_28698622.
msg236959 - (view) Author: SilentGhost (SilentGhost) * (Python triager) Date: 2015-03-01 12:23
There is this bit in https://docs.python.org/3/library/exceptions.html : 

> When raising a new exception (rather than using a bare raise to re-raise the exception currently being handled),...

I presume this can be also suitable for tutorial if it's not already there.
msg237493 - (view) Author: Martin Panter (martin.panter) * (Python committer) Date: 2015-03-08 01:49
For the Python 3 case, the documentation is vague and probably wrong, depending on what you understand “the current scope” to mean. I think it should read something like

. . . raise re-raises the current exception that is being handled. If no exception is being handled, a RuntimeError exception is raised indicating that this is an error.

I’m not sure but I suspect Python 2 is different because does not save the original exception when it handles a nested exception. In other words, at the point where the nested “bar” exception is raised inside the “foo” handler, Python forgets that “foo” was being handled.
msg247563 - (view) Author: Martin Panter (martin.panter) * (Python committer) Date: 2015-07-29 09:28
Here is a patch for Python 3. The re-raise behaviour reported by Antoine is already tested in test_raise.TestRaise.test_except_reraise().

My patch also clarifies some details about how __context__ is set:

* Context is the exception being handled, not necessarily the last exception
* “With” statements can influence context
* Re-raising does not set context; must be new exception object
* Add test case when context is not the last exception

I’m not so experienced with Python 2’s exception handling, so I haven’t got a patch for that. I suspect there is some shared “last exception” context. I wonder how it interacts with generators, multi-threading, __del__() and other callbacks, etc.
msg256907 - (view) Author: John Mark Vandenberg (jayvdb) * Date: 2015-12-23 11:23
In pyflakes we've looked at some of the strange scenarios where a raise without argument is 'legal'.  A patch to report errors for some of these was rejected because they are legal. See https://github.com/pyflakes/pyflakes/pull/57  The worst example of 'legal' is an exception in one module can be re-raised by another module.
msg405000 - (view) Author: Irit Katriel (iritkatriel) * (Python committer) Date: 2021-10-25 21:00
Martin's patch needs to be converted to a GitHub PR and then reviewed.
History
Date User Action Args
2021-10-27 13:10:44kinshukduasetkeywords: + patch
nosy: + kinshukdua
pull_requests: + pull_request27499
2021-10-25 21:00:36iritkatrielsetnosy: + iritkatriel
versions: + Python 3.9, Python 3.10, Python 3.11, - Python 2.7, Python 3.4, Python 3.5, Python 3.6
messages: + msg405000

keywords: + easy, - patch
title: Scope for raise without argument is different in Python 2 and 3 -> [doc] Scope for raise without argument is different in Python 2 and 3
2015-12-23 11:23:08jayvdbsetnosy: + jayvdb
messages: + msg256907
2015-07-29 09:28:16martin.pantersetfiles: + raise-scope-py3.patch
versions: + Python 3.5, Python 3.6
messages: + msg247563

keywords: + patch
stage: patch review
2015-07-21 07:23:29ethan.furmansetnosy: - ethan.furman
2015-03-14 00:13:44ethan.furmansetnosy: + ethan.furman
2015-03-08 01:49:34martin.pantersetassignee: docs@python

components: + Documentation
nosy: + docs@python
2015-03-08 01:49:13martin.pantersetmessages: + msg237493
2015-03-01 21:39:27martin.pantersetnosy: + martin.panter
2015-03-01 12:26:36SilentGhostsetnosy: + collinwinter
2015-03-01 12:23:21SilentGhostsetnosy: + SilentGhost
messages: + msg236959
components: + Interpreter Core
2015-03-01 12:14:32a3nmcreate