Printing unicode to windows terminal from scratch (2.7)

Python 2.7 is dying, but still, here is a way to print a unicode string without requiring users to edit python stdlib files or changing code pages (both being both scary and inconvenient).

I can’t imagine this being anything but excruciatingly slow, but for small use-cases it should be OK.

(oh, and it is not thread-safe, nor inter-process safe if processes are sharing a terminal)

# -*- coding: utf-8 -*-
from __future__ import print_function

import codecs
import contextlib
import os
import sys
from encodings import aliases


class UniTerm(object):
    def __init__(self):
        self.state = self.get_state()
        aliases.aliases['65001'] = 'utf_8'
        self.chcp = '65001'
        sys.stdout = codecs.getwriter('utf8')(sys.stdout)

    def get_state(self):
        return {
            'cp': self.chcp,
            'aliases': aliases.aliases.get('65001'),
            'stdout': sys.stdout
        }

    def reset(self):
        self.chcp = self.state['cp']
        if self.state['aliases'] is None:
            del aliases.aliases['65001']
        else:
            aliases.aliases['65001'] = self.state['aliases']
        sys.stdout = self.state['stdout']

    @property
    def chcp(self):
        return os.popen('chcp').read().split()[-1]

    @chcp.setter
    def chcp(self, cp):
        os.system('chcp {}>NUL'.format(cp))


def uprint(*args, **kwargs):
    if sys.platform != 'win32':
        return print(*args, **kwargs)
    t = None
    try:
        t = UniTerm()
        return print(*args, **kwargs)
    finally:
        if t is not None:
            t.reset()


@contextlib.contextmanager
def uterm():
    t = UniTerm()
    try:
        yield
    finally:
        t.reset()


if __name__ == '__main__':
    uprint(u'\u2713')  # checkmark
    with uterm():
        print(u'\u26a1')  # lightening bolt

output:

c:\> python uniterm.py

This entry was posted in Uncategorized. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *