homepage

This issue tracker has been migrated to GitHub , and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: Rename contextlib.ignore to contextlib.suppress
Type: enhancement Stage: resolved
Components: Library (Lib) Versions: Python 3.4
process
Status: closed Resolution: fixed
Dependencies: 15806 Superseder:
Assigned To: ncoghlan Nosy List: barry, belopolsky, ncoghlan, python-dev, r.david.murray, rhettinger, skrah, zero.piraeus
Priority: normal Keywords: patch

Created on 2013年10月15日 11:50 by ncoghlan, last changed 2022年04月11日 14:57 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
cligsu.patch zero.piraeus, 2013年10月15日 13:33 review
Messages (22)
msg199995 - (view) Author: Alyssa Coghlan (ncoghlan) * (Python committer) Date: 2013年10月15日 11:50
Issue 15806 added contextlib.ignored to the standard library (later renamed to contextlib.ignore), as a simple helper that allows code like:
 try:
 os.remove(fname)
 except FileNotFoundError:
 pass
to instead be written as:
 with ignore(FileNotFoundError):
 os.remove('somefile.tmp')
The point has been made that "ignore" may easily be taken to mean preventing the exception being raised *at all* (since truly ignoring the exception would mean not skipping the rest of the with statement), rather than suppressing the exception in the context manager's __exit__ method.
If you look at the rest of the contextlib docs, as well as the docs for the with statement and context manager objects, they don't refer to returning True from __exit__ as ignoring the exception, but rather as *suppressing* it. Even the docs for contextlib.ignore now make use of the term "suppress".
So I think it makes sense to rename the context manager to "suppress", while keeping the same semantics:
 with suppress(FileNotFoundError):
 os.remove('somefile.tmp')
msg199996 - (view) Author: Alyssa Coghlan (ncoghlan) * (Python committer) Date: 2013年10月15日 13:01
The specific docs quotes that persuaded me "suppress" was a better name than "ignore" for this feature (by contrast, "ignore" in this sense only appears in its own docs):
From http://docs.python.org/dev/library/stdtypes.html#contextmanager.__exit__:
"Exit the runtime context and return a Boolean flag indicating if any
exception that occurred should be suppressed."
"Returning a true value from this method will cause the with statement
to suppress the exception and continue execution with the statement
immediately following the with statement. "
From http://docs.python.org/dev/reference/datamodel.html#object.__exit__
"If an exception is supplied, and the method wishes to suppress the
exception (i.e., prevent it from being propagated), it should return a
true value."
From http://docs.python.org/dev/library/contextlib#contextlib.contextmanager
"If an exception is trapped merely in order to log it or to perform
some action (rather than to suppress it entirely), the generator must
reraise that exception."
From http://docs.python.org/dev/library/contextlib#contextlib.ignore (!)
"As with any other mechanism that completely suppresses exceptions, it
should only be used to cover very specific errors where silently
ignoring the exception is known to be the right thing to do."
From http://docs.python.org/dev/library/contextlib#contextlib.ExitStack
"...if an inner callback suppresses or replaces an exception, then
outer callbacks will be passed arguments based on that updated state."
From http://docs.python.org/dev/library/contextlib#contextlib.ExitStack.enter_context
"These context managers may suppress exceptions just as they normally
would if used directly as part of a with statement."
From http://docs.python.org/dev/library/contextlib#contextlib.ExitStack.push
"By returning true values, these callbacks can suppress exceptions the
same way context manager __exit__() methods can."
From http://docs.python.org/dev/library/contextlib#contextlib.ExitStack.callback
"Unlike the other methods, callbacks added this way cannot suppress
exceptions (as they are never passed the exception details)."
msg199997 - (view) Author: Zero Piraeus (zero.piraeus) * Date: 2013年10月15日 13:33
This is my first submitted patch; if there's anything wrong with it, please let me know (but the testsuite passes, and make patchcheck only warns about Misc/NEWS and Misc/ACKS, which I assume is handled by committer).
msg199998 - (view) Author: Alyssa Coghlan (ncoghlan) * (Python committer) Date: 2013年10月15日 13:55
Zero's patch looks good to me, but it may be a couple of days before I can get to applying it. If anyone else can handle it before then, please feel free :)
Also, Zero, if you could review and sign the contributor agreement, that would be great: http://www.python.org/psf/contrib/contrib-form/ (while this patch is mechanical enough to be OK without one, it's still good to take care of the formalities of granting the PSF clear redistribution rights for CPython contributions)
msg199999 - (view) Author: Zero Piraeus (zero.piraeus) * Date: 2013年10月15日 14:20
> Zero, if you could review and sign the contributor agreement, that
> would be great: http://www.python.org/psf/contrib/contrib-form/
Done :-)
msg200007 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2013年10月15日 16:28
This patch looks fine. I'll apply it shortly.
msg200037 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2013年10月16日 07:25
After more thought, I think that suppress() isn't as clear as ignore() and it doesn't read as well in typical use cases. I'm assigning this one back to Nick to decide.
If you want to scan existing code for examples to see how well this would read, run this:
 $ egrep -C2 "except( [A-Za-z]+)?:" *py | grep -C2 "pass"
msg200039 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2013年10月16日 07:47
On python-dev, abort_on() and trap() were proposed.
msg200044 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2013年10月16日 09:11
I oppose abort_on() because it implies that it aborts the program.
The word trap() is accurate but will be weird-sounding and non-communicative to users without a CS background:
 with trap(sqlite3.OperationalError):
 cursor.execute('CREATE TABLE dict (key text, value text)')
The word "trap" in a CS context is also archaic and falling out of use. (Remember, glob.glob() was a good name in 1990 but most people now don't get know the reference to "globbing" and so the word is meaningless gobbledygook to them).
Please give some weight to the fact the ignore() was checked in for seven months, it was presented at a conference, I've put it front of working Python programmers to use in real code, and I've checked to see how it reads in the try/except/pass code examples in the standard library. Don't throw away this work on a whim.
msg200052 - (view) Author: Stefan Krah (skrah) * (Python committer) Date: 2013年10月16日 10:18
trap() is a bit ambiguous, since in floating point operations it
means that something is actually raised and not suppressed. So one
could write:
from decimal import *
c = getcontext()
c.traps[Inexact] = True
>>> Decimal(9) / 11 # raises now!
with trap(Inexact):
 Decimal(9) / 11 # quiet!
As for "ignore" vs. "suppress", I'm with the people who think that they
are largely synonyms here. I find "ignore" slightly catchier and nicer
to read. Being pedantic, one could call it "ignore_once".
I would also like "catch", or pedantically, "catch_once".
msg200054 - (view) Author: Zero Piraeus (zero.piraeus) * Date: 2013年10月16日 12:16
'Ignore' and 'suppress' are not synonyms:
https://www.google.com/search?q=define%3Asuppress
> forcibly put an end to.
> "the rising was savagely suppressed"
> synonyms: subdue, repress, crush, quell, quash, squash, stamp out
https://www.google.com/search?q=define%3Asuppress
> refuse to take notice of or acknowledge; disregard intentionally.
> "he ignored her outraged question"
> synonyms: disregard, take no notice of, pay no attention to [...]
I know that ncoghlan and rhettinger (and maybe others) are annoyed by what they see as bikeshedding, but there is a genuine issue here. To summarize the objection raised on python-dev, the problem is that this:
 with ignore(SomeException):
 do_something()
 do_something_else()
... is easily misunderstood as ignoring every occurrence of SomeException throughout the with-statement. 
If you understand how context managers work, it's not difficult to see why that's not the case, but the name strongly suggests the incorrect reading over the correct one.
I don't think 'suppress' is perfect. At the risk of further enraging those who are already tired of this discusion, I'll re-propose 'silence', which IMO comes closest to describing what is actually going on:
https://www.google.com/search?q=define%3Asilence
> cause to become silent; prohibit or prevent from speaking.
> "the team's performance silenced their critics"
> synonyms: quiet, hush, shush
I also quite like 'quash' from the list of 'suppress' synonyms above, but that's probably just because it's a nice word to say :-)
msg200056 - (view) Author: Stefan Krah (skrah) * (Python committer) Date: 2013年10月16日 12:28
Zero Piraeus <report@bugs.python.org> wrote:
> 'Ignore' and 'suppress' are not synonyms:
I wrote "synonyms here", meaning that in *this context* they are practically
synonyms. "suppress" describes the mechanics more precisely, "ignore"
descibes the human intent: suppress_and_thereby_ignore.
msg200091 - (view) Author: Alexander Belopolsky (belopolsky) * (Python committer) Date: 2013年10月16日 22:40
> Please give some weight to the fact the ignore() was
> checked in for seven months, ...
+1
msg200092 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2013年10月16日 22:55
Yes, in this context ingnore, suppress, and silence all have essentially the same problem, or lack of it, depending on your point of view.
Catch would be fine with me :)
Please note that someone *reading the thread* on python-dev misunderstood what ignore did after *reading the documentation*. So, whether or not the name is changed, the documentation should be updated to stress the fact that the with block is exited as soon as the exception is raised for the first time.
msg200093 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2013年10月16日 23:02
To be clear: I do think 'suppress' is better than 'ignore', for the reasons Nick articulated.
msg200094 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2013年10月16日 23:04
On Oct 16, 2013, at 3:55 PM, R. David Murray <report@bugs.python.org> wrote:
> Catch would be fine with me :)
I like "catch".
Raymond
msg200095 - (view) Author: Alyssa Coghlan (ncoghlan) * (Python committer) Date: 2013年10月16日 23:18
I didn't choose suppress on a whim. I actually agree with Raymond that
ignore reads better when the context manager is used correctly, but
suppress is more consistent with the terminology used in the documentation
(including even PEP 343), *and* I think it is slightly less vulnerable to
people expecting it to mean "don't even raise the exception and continue
with the next statement inside the with block" (aka the "on error resume
next" misinterpretation).
I think suppress reads *well enough* for it to be worth making the switch
in order to gain those other benefits.
msg200096 - (view) Author: Alyssa Coghlan (ncoghlan) * (Python committer) Date: 2013年10月16日 23:21
The reason I specifically *don't* like trap or catch for this is that they
both have "... and do something with it" connotations for me, whereas
ignore and suppress both appropriately imply "... and silently discard it".
msg200097 - (view) Author: Alexander Belopolsky (belopolsky) * (Python committer) Date: 2013年10月16日 23:24
> Catch would be fine with me :)
Both "catch" and "trap" have the same problem in my view: you don't get to eat what you have caught (or trapped). :-)
> Please note that someone *reading the thread* on python-dev
> misunderstood what ignore did after *reading the documentation*.
I question whether the confusion was genuine. Anyone who has discovered contextlib modules should know enough about with statement, context managers and exceptions to understand how ignore() can work. Sky is the limit when it comes to documentation improvements, but in this case code is better than a thousand words:
 @contextmanager
 def ignore(*exceptions):
 """Context manager to ignore particular exceptions"""
 try:
 yield
 except exceptions:
 pass
Here is how I understand the word "ignore" in the context of context managers. (Pun unavoidable.) The context manager implements logic of how to exit the with block. The logic of ignore() CM is to (drum roll, please) ignore the specified exception(s) if any is raised within the with block.
I gave my +0 to "suppress" on the list, but with more thought and considering more examples, I like "ignore" best. It is still a close call, but "suppress" suggests more effort on the part of CM than there is.
msg200098 - (view) Author: Alyssa Coghlan (ncoghlan) * (Python committer) Date: 2013年10月16日 23:29
Agreed it's a close call - it's really the docs consistency issue that
tipped the balance for me, since I think either ignore *or* suppress would
be a suitable name for the pattern when used correctly.
msg200100 - (view) Author: Alexander Belopolsky (belopolsky) * (Python committer) Date: 2013年10月16日 23:38
Feel free to ignore() me if it helps to close this debate. English is not my native language and my understanding may not match that of the majority of users.
Note, however, that this debate might not even have started if not for a change s/ignored/ignore/. The s/ignore/suppress/ commit may sparkle yet another round.
(It is quite possible that my dislike of "suppress" stems from not being able to remember how many p's and s's this word has in its spelling. As I said - feel free to ignore me.)
msg200126 - (view) Author: Roundup Robot (python-dev) (Python triager) Date: 2013年10月17日 13:42
New changeset 22247b7d17fa by Nick Coghlan in branch 'default':
Close #19266: contextlib.ignore -> contextlib.suppress
http://hg.python.org/cpython/rev/22247b7d17fa 
History
Date User Action Args
2022年04月11日 14:57:52adminsetgithub: 63465
2013年10月17日 13:42:52python-devsetstatus: open -> closed

nosy: + python-dev
messages: + msg200126

resolution: fixed
stage: needs patch -> resolved
2013年10月16日 23:47:02vstinnersetnosy: - vstinner
2013年10月16日 23:38:18belopolskysetmessages: + msg200100
2013年10月16日 23:29:47ncoghlansetmessages: + msg200098
2013年10月16日 23:24:02belopolskysetmessages: + msg200097
2013年10月16日 23:21:37ncoghlansetmessages: + msg200096
2013年10月16日 23:18:19ncoghlansetmessages: + msg200095
2013年10月16日 23:04:47rhettingersetmessages: + msg200094
2013年10月16日 23:02:59r.david.murraysetmessages: + msg200093
2013年10月16日 22:55:11r.david.murraysetnosy: + r.david.murray
messages: + msg200092
2013年10月16日 22:40:48belopolskysetnosy: + belopolsky
messages: + msg200091
2013年10月16日 22:31:55belopolskylinkissue15806 superseder
2013年10月16日 22:31:31belopolskysetdependencies: + Add context manager for the "try: ... except: pass" pattern
2013年10月16日 12:28:30skrahsetmessages: + msg200056
2013年10月16日 12:16:59zero.piraeussetmessages: + msg200054
2013年10月16日 10:18:46skrahsetnosy: + skrah
messages: + msg200052
2013年10月16日 09:11:29rhettingersetmessages: + msg200044
2013年10月16日 07:47:50vstinnersetnosy: + vstinner
messages: + msg200039
2013年10月16日 07:25:20rhettingersetassignee: rhettinger -> ncoghlan
messages: + msg200037
2013年10月15日 16:28:43rhettingersetassignee: rhettinger
messages: + msg200007
2013年10月15日 14:20:31zero.piraeussetmessages: + msg199999
2013年10月15日 13:55:00ncoghlansetmessages: + msg199998
2013年10月15日 13:33:30zero.piraeussetfiles: + cligsu.patch

nosy: + zero.piraeus
messages: + msg199997

keywords: + patch
2013年10月15日 13:15:30barrysetnosy: + barry
2013年10月15日 13:01:29ncoghlansetmessages: + msg199996
2013年10月15日 11:50:54ncoghlancreate

AltStyle によって変換されたページ (->オリジナル) /