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: Inaccessible attribute characters_written on OSError instances
Type: behavior Stage: resolved
Components: Library (Lib) Versions: Python 3.6
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: Nosy List: Igor Kozyrenko (ikseek), r.david.murray, xiang.zhang
Priority: normal Keywords:

Created on 2017-06-02 16:01 by Igor Kozyrenko (ikseek), last changed 2022-04-11 14:58 by admin. This issue is now closed.

Messages (6)
msg295030 - (view) Author: Igor Kozyrenko (ikseek) (Igor Kozyrenko (ikseek)) Date: 2017-06-02 16:01
If I enumerate attributes on OSError instance with dir
dir(OSError())
I see an 'characters_written' attribute (which is supposed to be defined on BlockingIOError according to docs).
If I try to access it
getattr(OSError(), 'characters_written')
I get an AttributeError
msg295037 - (view) Author: Xiang Zhang (xiang.zhang) * (Python committer) Date: 2017-06-02 16:44
Actually the docs says "This attribute is available when using the buffered I/O classes from the io module", which means it's not always available since it depends on an inner field set or not.

It's just like Python code:

>>> class CW:
...     def __get__(self, obj, objtype):
...             if obj._written:
...                     return obj._written
...             else:
...                     raise AttributeError("characters_written")
...     def __set__(self, obj, val):
...             obj._written = val
... 
>>> class MyOSError:
...     characters_written = CW()
...     def __init__(self):
...             self._written = False
... 
>>> dir(MyOSError())
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_written', 'characters_written']
>>> MyOSError().characters_written
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 6, in __get__
AttributeError: characters_written
msg295042 - (view) Author: Igor Kozyrenko (ikseek) (Igor Kozyrenko (ikseek)) Date: 2017-06-02 17:30
So is it by design?
cgitb library fails to create report if there are links to exceptions based on OSError on the stack because it tries to enumerate all it's attributes.
msg295043 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2017-06-02 17:42
That's actually a very good question.  hasattr returns False, but is it supposed to be an invariant that if dir returns a string hasattr should return True and getattr should not return AttributeError?  (Well, it might raise AttributeError from inside the attribute, but the attribute itself should be "real".)  Or to put it the other way, if hasattr returns False, should it be an invariant that dir does not list that attribute name?

This may be a question for python-dev, and the answer may well be that we do *not* want to suggest that such an invariant should be expected.  (We of course don't enforce such things, but we do make them hold true in the stdlib if we establish them).  However, it is certainly a surprising behavior, and Python *generally* tries to avoid such surprises.

This may have already been discussed and decided at some previous point, so someone should do some docs and archive searching about it first :)
msg295048 - (view) Author: Xiang Zhang (xiang.zhang) * (Python committer) Date: 2017-06-02 18:23
Looking at the code and doc it seems it's by design. But it's good or not remains in question. The related discussion about the more general problem behind this issue is https://groups.google.com/d/msg/python-ideas/Kou5cYGjGQ8/oXEixwgiDwAJ. There is a workaround and a proposed general resolution. But it's hard for me now to treat the current OSError behaviour as a *bug*.
msg295053 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2017-06-02 20:36
Thank you for linking to that Xiang.  I had a vague memory of that discussion but couldn't find it.

No, there is no bug here, but there is a question of whether or not there *should* be a bug here (that is, is there a design bug) and if so how/where to fix it :)

This issue isn't the place to have that discussion.
History
Date User Action Args
2022-04-11 14:58:47adminsetgithub: 74739
2017-08-02 20:35:42r.david.murraylinkissue31111 superseder
2017-06-02 20:36:52r.david.murraysetmessages: + msg295053
2017-06-02 18:23:16xiang.zhangsetmessages: + msg295048
2017-06-02 17:42:10r.david.murraysetnosy: + r.david.murray
messages: + msg295043
2017-06-02 17:30:38Igor Kozyrenko (ikseek)setmessages: + msg295042
2017-06-02 16:44:50xiang.zhangsetstatus: open -> closed

nosy: + xiang.zhang
messages: + msg295037

resolution: not a bug
stage: resolved
2017-06-02 16:01:56Igor Kozyrenko (ikseek)create