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
✓
⚡