Ошибка Python os.walk и japanese filename

Возможный дубликат:
Python, Unicode и консоль Windows

У меня есть папка с именем файла "01 – ナ ナ ナ ン 塊 .txt"

Я открываю python в интерактивном приглашении в той же папке, что и файл, и пытаюсь перейти к папке hierachy:

Python 3.1.2 (r312:79149, Mar 21 2010, 00:41:52) [MSC v.1500 32 bit (Intel)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> import os >>> for x in os.walk('.'): ... print(x) ... Traceback (most recent call last): File "<stdin>", line 2, in <module> File "C:\dev\Python31\lib\encodings\cp850.py", line 19, in encode return codecs.charmap_encode(input,self.errors,encoding_map)[0] UnicodeEncodeError: 'charmap' codec can't encode characters in position 17-21: character maps to <undefined> 

Очевидно, что кодировка, которую я использую, не способна обрабатывать японские символы. Хорошо. Но Python 3.1 должен быть unicode полностью вниз, как я понимаю, поэтому я не понимаю, что я должен делать с этим. У кого-нибудь есть идеи?

Кажется, что все ответы до сих пор относятся к людям Unix, которые полагают, что консоль Windows похожа на терминал Unix, которого нет.

Проблема заключается в том, что вы не можете писать Unicode-вывод на консоль Windows, используя обычные функции ввода-вывода файлов. Необходимо использовать Windows API WriteConsole . Вероятно, Python должен делать это прозрачно, но это не так.

Существует другая проблема, если вы перенаправляете вывод в файл: текстовые файлы Windows исторически находятся в кодовой странице ANSI, а не в Unicode. Вы можете смело писать UTF-8 в текстовые файлы в Windows в эти дни, но Python этого не делает по умолчанию.

Я думаю, что он должен это делать, но вот какой-то код, чтобы это произошло. Вам не нужно беспокоиться о деталях, если вы этого не хотите; просто вызовите ConsoleFile.wrap_standard_handles (). Вам необходимо установить PyWin, чтобы получить доступ к необходимым API.

 import os, sys, io, win32api, win32console, pywintypes def change_file_encoding(f, encoding): """ TextIOWrapper is missing a way to change the file encoding, so we have to do it by creating a new one. """ errors = f.errors line_buffering = f.line_buffering # f.newlines is not the same as the newline parameter to TextIOWrapper. # newlines = f.newlines buf = f.detach() # TextIOWrapper defaults newline to \r\n on Windows, even though the underlying # file object is already doing that for us. We need to explicitly say "\n" to # make sure we don't output \r\r\n; this is the same as the internal function # create_stdio. return io.TextIOWrapper(buf, encoding, errors, "\n", line_buffering) class ConsoleFile: class FileNotConsole(Exception): pass def __init__(self, handle): handle = win32api.GetStdHandle(handle) self.screen = win32console.PyConsoleScreenBufferType(handle) try: self.screen.GetConsoleMode() except pywintypes.error as e: raise ConsoleFile.FileNotConsole def write(self, s): self.screen.WriteConsole(s) def close(self): pass def flush(self): pass def isatty(self): return True @staticmethod def wrap_standard_handles(): sys.stdout.flush() try: # There seems to be no binding for _get_osfhandle. sys.stdout = ConsoleFile(win32api.STD_OUTPUT_HANDLE) except ConsoleFile.FileNotConsole: sys.stdout = change_file_encoding(sys.stdout, "utf-8") sys.stderr.flush() try: sys.stderr = ConsoleFile(win32api.STD_ERROR_HANDLE) except ConsoleFile.FileNotConsole: sys.stderr = change_file_encoding(sys.stderr, "utf-8") ConsoleFile.wrap_standard_handles() print("English 漢字 Кири́ллица") 

Это немного сложно: если stdout или stderr – это консоль, нам нужно выводить с помощью WriteConsole; но если это не (например, файл foo.py>), это не сработает, и нам нужно вместо этого изменить кодировку файла на UTF-8.

Противоположность в любом случае не будет работать. Вы не можете выводить в обычный файл с помощью WriteConsole (это не байтовый API, а UTF-16, PyWin скрывает эту деталь), и вы не можете писать UTF-8 на консоль Windows.

Кроме того, на самом деле нужно использовать _get_osfhandle для получения дескриптора stdout и stderr, вместо того, чтобы предполагать, что они назначены стандартным дескрипторам, но у этого API нет привязки к PyWin.

Для жестко закодированных строк вам нужно указать кодировку в верхней части исходных файлов . Для ввода байтов из какого-либо другого источника, такого как os.walk , вам нужно указать кодировку байтовой строки (см. Ответ unutbu).