Trunk and release26-maint were recently changed (r71657, r71658) to use
the following logic, which differs from the code snippet you posted.

                   if (isinstance(msg, unicode) and
                       getattr(stream, 'encoding', None)):
                       stream.write(fs.decode(stream.encoding) % msg)
                   else:
                       stream.write(fs % msg)

If the stream is stderr and you are passing a unicode msg, the else
branch will not be taken; as long as the stream has an encoding
attribute, it should output correctly.

The change was made when another, similar issue was posted by another
user (issue #5768).

Can you confirm what happens with the current code as it is in
release26-maint? спасибо!
 
it still doesn't work for console (but OK for files).

the following works in both cases:
if (isinstance(msg, unicode) and
    getattr(stream, 'encoding', None) and
    (stream == sys.stdout or stream == sys.stderr)):
    stream.write(fs % msg.encode(stream.encoding))
else:
     stream.write(fs % msg)

i think it's all about the difference betwin print(msg) and sys.stdout.write('%s\n' % msg)

shamil