str
with one argument calls the __str__
of that argument. That call is expected to succeed, and return a string, because it is used - among other places - by print()
. Imagine if something like this could happen everytime you did print(bytes_object)
:
>>> class Chaos:
... def __str__(self):
... assert False
...
>>> print(Chaos())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in __str__
AssertionError
The only way this is allowed to fail is if the class doesn't define __str__
, in which case str
falls back to repr
.
On the other hand, str
with an encoding isn't called by print, and explicitly only supports objects that expose the Buffer API.
So, that leaves the question of what to do for str(bytes_object)
without an encoding, if it can't fail. The fact that the errors
argument defaults to strict
means it can't really assume any encoding, even though the docs say it will use sys.getdefaultencoding()
. It could do to have set the default errors
to something looser like ignore
, but there's good reasons not to do that - especially, it goes against the Zen of Python:
Errors should never pass silently.
Unless explicitly silenced.
And this case is particularly bad: it is quite easy to imagine it silently doing the wrong thing, but looking, on the dev's machine, like it's doing the right thing, only to randomly lose data in other environments (remember that sys.getdefaultencoding()
is affected by the locale settings Python is currently running under). So, str(bytes_object)
without an encoding is probably an error in most cases, but it still can't fail the normal way - so it does the next best thing: it produces output that is clearly wrong in all cases that you meant to call it with an explicit encoding.