Override builtin type __str__ method in python
<p>I need to port some code from Python2 to Python3 and the main problem seems to be in bytes type, because str(bytes) gives me "b'%s'" result, but '%s' is needed, so I decided to override __str__() method of bytes class to print exactly what I want.</p>

<p>I tried to patch builtins.bytes with class inherited from bytes, but that seem to work only for one file and not for the whole project and also does not affect on bytesliterals (b'').</p>

<p>If there are any other ways (less painful) to port from py2 to py3, it would be nice to see them.</p>

<p>Using .decode('UTF-8') is not acceptable, because the project is more than 4k lines and adding decode method to all necessary places would result in progressive bugs count, and also some of those .decode places are in 3-rd party libraries.</p>

<p>I tried to do something like this:</p>

<pre><code>import builtins

class StrBytes(builtins.bytes):
    def __str__(self):
        return self.decode('UTF-8')

builtins.bytes = StrBytes
</code></pre>

<p>Then if I use bytes() it creates StrBytes object and str(bytes()) is exactly what I want. This way is bad because it does not cover constructing bytes object from bytesliteral:</p>

<pre><code>&gt;&gt;&gt; type(bytes())
    &lt;class 'StrBytes'&gt;

&gt;&gt;&gt; type(b'')
    &lt;class 'bytes'&gt;
</code></pre>

<p>And I am not certain if it works for the whole project, not only one file.</p>

<p>In many different places of my code, I have something like this:</p>

<pre><code>return b''.join(some_extra_values)

keys = [b'1', b'2', b'3'] # actually keys are given from another part of code
for key in keys:
    some_dict[key] = some_value

some_dict['1'] # works in py2, not in py3, KeyError
</code></pre>

<p>The rule with text is "decode on input, encode on output." Although a lot of work has been done to make it easier to write code that is compatible between v2 and v3, there are always going to be some discrepancies and the fact that Python 3 no longer defines the <code>unicode</code> symbol is one of them.</p>

<p>It isn't a good idea to try and patch the built-in types in Python. Because they are defined in C there is no effective way to patch their methods.</p>

<p>One possibly useful tool is</p>

<pre><code>from __future__ import unicode_literals
</code></pre>

<p>when, when inserted at the beginning of the program will interpret all string literals as Unicode strings rather than bytestrings.</p>

<p>Another way to adapt your code is to use the fact that Python 3 doesn't implement the <code>unicode</code> name to drive feature detection. So you might write, for example</p>

<pre><code>try:
    unicode = unicode # RHS raises NameError on Python 3
except NameError:
    unicode = str
</code></pre>

<p>Then you can check for text types by writing</p>

<pre><code>if type(s) is unicode: 
    ...
</code></pre>

<p>and the comparisons should work in both v2 and v3.</p>

<p>You should NOT have to insert many calls to decode if you correctly decode on input, and should only need to encode when the string has to be communicated to an external tool of some kind.</p>

python decode 2to3 builtins