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: Add a 'key' attribute to KeyError
Type: enhancement Stage: test needed
Components: Versions:
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: aroberge, barry, brett.cannon, cvrebert, ezio.melotti, platonoff-dev, r.david.murray, rhettinger, sblondon, zingero
Priority: normal Keywords:

Created on 2013年06月07日 20:51 by brett.cannon, last changed 2022年04月11日 14:57 by admin.

Messages (12)
msg190778 - (view) Author: Brett Cannon (brett.cannon) * (Python committer) Date: 2013年06月07日 20:51
KeyError could grow a 'key' attribute for the key that triggered the exception. Since keys are expected to be immutable (in order to be hashable) there is no GC issue to worry about.
msg190782 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2013年06月07日 21:11
I don't see how the fact that keys are immutable implies there are no GC issues. A tuple can be involved in a cycle, for example.
msg190786 - (view) Author: Brett Cannon (brett.cannon) * (Python committer) Date: 2013年06月08日 01:43
So are you arguing it should be a weakref, or just saying you view the statement as false?
msg190791 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2013年06月08日 02:18
I'm arguing that the statement is false. I think that whether or not it should be a weakref in this and the other cases depends on whether you think an exception object should keep an object alive or not. It is fairly unlikely that a key would get into a cycle with an error message, though certainly not impossible.
The "keep alive" question probably boils down to whether or not we want it to be the case that clearing the traceback attribute releases all the "extra" pointers an exception holds on to, or if it is acceptable that an arbitrary number of additional attributes might do so.
I'm inclined to think that using weakrefs would make using the attributes more complicated for relatively little gain.
msg190999 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2013年06月12日 00:46
Since the key is already accessible via the "args" attribute, what is the point of a new attribute?
>>> d = {}
>>> try:
	d['roger']
except KeyError as e:
	print(e.args)
	
('roger',)
msg191001 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2013年06月12日 01:39
Making it unambiguous what piece of data is being retrieved, and allowing new code to have a more complex message than just 'Keyerror: xxxx' and still be able to get at only the missing key.
msg191038 - (view) Author: Brett Cannon (brett.cannon) * (Python committer) Date: 2013年06月12日 17:36
What David said. =)
The fact that the key is the first value from args is almost happenstance as the exception message is customized in __str__() and not in what is passed to the exception. But what if I had defined __getattr__ or __getattribute__ and had some prefix requirement? It would be more helpful to say ``KeyError("{!r} does not start with py_".format(key))`` which breaks your args[0] usage but is a much more descriptive message and has no defined way to provide the key as an attribute.
It's basically "explicit is better than implicit" since there is no API guarantee that the first thing in 'args' for KeyError will in actuality be the key.
msg191083 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2013年06月13日 15:47
+1. I recently chastised a colleague for doing "raise KeyError(long_message)" instead of "raise KeyError(missing_item)". When I went to the standard library to support my POV, I found (to my chagrin) a big mix of the two styles.
>>> from collections import ChainMap
>>> d = ChainMap({}, {})
>>> try:
... d.pop('not there')
... except KeyError as e:
... key, = e.args
... 
>>> key
"Key not found in the first mapping: 'not there'"
msg378075 - (view) Author: Orian Zinger (zingero) Date: 2020年10月05日 20:39
Hi all,
As a Python developer, I encountered lots of blurry exception messages in the product logs such as:
<time and date> <process name> <log severity> Failed to do something. Exception: 'some key'
I believe printing the key name without explaining the exception itself is bad (explicit is better than implicit).
Thus, after forking the repository, I added a short explanation about the Exception.
Now, it looks like:
>>> try:
... {}['some key']
... except Exception as e:
... print(e)
... 
Missing key: some key
I'm a newbie in a contribution to CPython, so please let me know if the idea behind my commit is good. If not, please explain how can I improve my commit so it'll be pulled later to the main branch.
https://github.com/zingero/cpython/commit/8c9e5d9e16296cee1f3ec05638dd6989dae8b811
Regards,
Orian.
msg378253 - (view) Author: Anatoliy Platonov (platonoff-dev) * Date: 2020年10月08日 15:54
I agree with Mark. I will be useful to provide ability to specify custom long message for error. And logically it would be better to do not allow users change key field in error so easy.
msg383445 - (view) Author: Stéphane Blondon (sblondon) * Date: 2020年12月20日 20:39
Orian: your patch formats the error message but the original suggested solution is to store the missing key in a new attribute. 
I don't know if you go in the good direction.
Adding an attribute is also suggested by issue #614557.
msg386890 - (view) Author: Stéphane Blondon (sblondon) * Date: 2021年02月12日 23:10
I'm interested by such feature.
I see examples of versions of the message provided by KeyError:
- sometimes with a message (for example `PyErr_SetString(PyExc_KeyError, "name too long");` at [1])
- sometimes with the missing key (for example `PyErr_SetObject(PyExc_KeyError, key);` at [2])
It explains why there is a difference in the messages in KeyError (as said in previous messages).
PyErr_SetString(), PyErr_Format(), PyErr_FormatV() (implemented in Python/errors.c) don't have a parameter to set the missing key. So I think it would be easier to set the missing attribute before calling thoses functions.
According to [3], the C PyExc_KeyError matches the Python KeyError exception.
So I think to:
- Add a 'missing_key' attribute to KeyError_str (in [4])
- Add the missing key to PyExc_KeyError instance before the call of PyErr_SetString(), PyErr_SetObject(), etc.
Do you think such strategy is doable?
What do you think about it? Is it the way you think about it? If not, do you have some hint?
I already made some minor patches to cpython but only in the Python part, never in C one.
1: https://github.com/python/cpython/blob/master/Modules/unicodedata.c#L1398
2: https://github.com/python/cpython/blob/master/Python/hamt.c#L2767
3: https://docs.python.org/3/c-api/exceptions.html?highlight=pyerr_format#standard-exceptions
4: https://github.com/python/cpython/blob/master/Objects/exceptions.c#L1569 
History
Date User Action Args
2022年04月11日 14:57:46adminsetgithub: 62363
2021年02月18日 18:52:19arobergesetnosy: + aroberge
2021年02月18日 18:11:01mark.dickinsonsetnosy: - mark.dickinson
2021年02月12日 23:10:10sblondonsetmessages: + msg386890
2020年12月20日 20:39:21sblondonsetnosy: + sblondon

messages: + msg383445
versions: - Python 3.4
2020年10月08日 15:54:35platonoff-devsetnosy: + platonoff-dev
messages: + msg378253
2020年10月05日 20:40:25zingerosetcomponents: - Library (Lib)
2020年10月05日 20:39:11zingerosetnosy: + zingero
messages: + msg378075
components: + Library (Lib), - Interpreter Core
2013年06月15日 21:05:57ezio.melottisetnosy: + ezio.melotti
2013年06月14日 16:20:42cvrebertsetnosy: + cvrebert
2013年06月13日 15:47:53mark.dickinsonsetnosy: + mark.dickinson
messages: + msg191083
2013年06月12日 17:36:23brett.cannonsetmessages: + msg191038
2013年06月12日 01:39:51r.david.murraysetmessages: + msg191001
2013年06月12日 00:46:23rhettingersetnosy: + rhettinger
messages: + msg190999
2013年06月08日 02:18:37r.david.murraysetmessages: + msg190791
2013年06月08日 01:43:43brett.cannonsetmessages: + msg190786
2013年06月07日 21:23:14barrysetnosy: + barry
2013年06月07日 21:11:01r.david.murraysetnosy: + r.david.murray
messages: + msg190782
2013年06月07日 20:51:56brett.cannoncreate

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