Issue 30554: Inaccessible attribute characters_written on OSError instances (original) (raw)
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 "", line 1, in File "", line 6, in get AttributeError: characters_written
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 :)