from __future__ import unicode_literals from __future__ import print_function import sys import io from ctypes import * from ctypes.wintypes import * GetConsoleOutputCP = WINFUNCTYPE(UINT)(('GetConsoleOutputCP', windll.kernel32)) WideCharToMultiByte = WINFUNCTYPE(c_int, UINT, DWORD, LPCWSTR, c_int, c_void_p, c_int, LPCSTR, POINTER(BOOL))(('WideCharToMultiByte', windll.kernel32)) class WinConOut(io.TextIOWrapper): def __init__(self, handle, *args, **kwargs): if not sys.platform.startswith('win32') or not handle.isatty(): raise ValueError('WinConOut buffer must be a win32 tty') # Get binary file handle if hasattr(handle, 'buffer') and hasattr(handle.buffer, 'raw'): buffer = handle.buffer.raw # Python 3.4 else: buffer = io.open(handle.fileno(), 'wb', 0, closefd = False) # Python 2.7 io.TextIOWrapper.__init__(self, buffer, *args, **kwargs) # def write(self, str): cp = GetConsoleOutputCP() lenC = len(str) lenB = WideCharToMultiByte(cp, 0, str, lenC, None, 0, None, None) buf = create_string_buffer(lenB) WideCharToMultiByte(cp, 0, str, lenC, buf, lenB, None, None) self.buffer.write(buf.raw[:lenB]) self.flush() def test(tcs, msg = None): if msg: try: print(msg) except: pass for tc in tcs: try: print(tc) except: pass try: print('') except: pass if __name__ == '__main__': # some codepoints from http://rubytester.github.io/2013/07/09/unicode-for-testers/ testchars = [ '\u00A3', # Pound Sterling '\u00DF', # German Sharp S '\u00F3', # o with acute '\u0119', # Polish e with ogonek '\u042F', # Russian Ya '\u03BB', # Greek lambda '\uFB02', # Highest codepoint in Lucida Console Font '\u2603', # Snowman '\u2708', # Airplane '\u0BF8', # Tamil char '\u2713', # Checkmark '\U00020000', # CJK Extension B '\U00020001', # CJK Extension B '\U00020002'] # CJK Extension B # Testing done with Lucida Console Font # With chcp 437 Raster Font works otherwise gibberish for codepoints > 127 # Characters not represented in a codepage are printed as '?' # Characters not in the font are printed as boxes # I assume such characters would dischcpplay correctly with the correct font # I gave up trying get another font working with the windows console test(testchars, 'testing default sys.stdout') # Under chcp 437 and 1252 first 3 are correct, rest raise exceptions # Under chcp 65001 python27 cp65001 isn't recognized raising exceptions # Under chcp 65001 python34 first 7 are correct but with extra line break # Remaining characters are boxes so presumably correct # Possible issue with CJK as each resulted in two boxes sys.stdout = WinConOut(sys.stdout) test(testchars, 'testing WinConOut(sys.stdout)') # Under chcp 437 and 1252 the first 4 are correct the rest are ?s # Under chcp 437 the checkmark is also correct # Under chcp 65001 the first 7 are correct the rest are boxes # Possible issue under python27 with CJK as each results in 2 boxes/?s try: print('done') except: pass