Чтение символов Юникода из аргументов командной строки в Python 2.x в Windows

Я хочу, чтобы мой скрипт Python мог читать аргументы командной строки Unicode в Windows. Но похоже, что sys.argv – это строка, закодированная в некотором локальном кодировании, а не в Unicode. Как я могу прочитать командную строку в полном Unicode?

Пример кода: argv.py

 import sys first_arg = sys.argv[1] print first_arg print type(first_arg) print first_arg.encode("hex") print open(first_arg) 

На моем ПК, настроенном для японской кодовой страницы, я получаю:

 C:\temp>argv.py "PC・ソフト申請書08.09.24.doc" PC・ソフト申請書08.09.24.doc <type 'str'> 50438145835c83748367905c90bf8f9130382e30392e32342e646f63 <open file 'PC・ソフト申請書08.09.24.doc', mode 'r' at 0x00917D90> 

Я полагаю, что это Shift-JIS закодирован, и он «работает» для этого имени файла. Но он разбивается на имена файлов с символами, которые не находятся в наборе символов Shift-JIS – окончательный «открытый» вызов завершается с ошибкой:

 C:\temp>argv.py Jörgen.txt Jorgen.txt <type 'str'> 4a6f7267656e2e747874 Traceback (most recent call last): File "C:\temp\argv.py", line 7, in <module> print open(first_arg) IOError: [Errno 2] No such file or directory: 'Jorgen.txt' 

Примечание. Я говорю о Python 2.x, а не Python 3.0. Я обнаружил, что Python 3.0 дает sys.argv как правильный Unicode. Но еще немного до перехода на Python 3.0 (из-за отсутствия поддержки сторонней библиотеки).

Обновить:

Несколько ответов сказали, что я должен декодировать в соответствии с тем, что закодировано sys.argv . Проблема заключается в том, что он не является полным Unicode, поэтому некоторые символы не представляются.

Вот прецедент, который дает мне печаль: я включил drag-and-drop файлы на .py-файлы в Проводнике Windows . У меня есть имена файлов со всеми типами символов, в том числе некоторые не на системной странице кода по умолчанию. Мой скрипт Python не получает правильные имена файлов Unicode, переданные ему через sys.argv во всех случаях, когда символы не могут быть представлены в текущей кодировке кодовой страницы.

Конечно, есть некоторый Windows API для чтения командной строки с полным Unicode (и Python 3.0 делает это). Я предполагаю, что интерпретатор Python 2.x не использует его.

4 Solutions collect form web for “Чтение символов Юникода из аргументов командной строки в Python 2.x в Windows”

Вот решение, которое именно я ищу, делая вызов функции GetCommandLineArgvW Windows:
Получите sys.argv с символами Unicode под Windows (из ActiveState)

Но я сделал несколько изменений, чтобы упростить его использование и лучше обрабатывать определенные виды использования. Вот что я использую:

win32_unicode_argv.py

 """ win32_unicode_argv.py Importing this will replace sys.argv with a full Unicode form. Windows only. From this site, with adaptations: http://code.activestate.com/recipes/572200/ Usage: simply import this module into a script. sys.argv is changed to be a list of Unicode strings. """ import sys def win32_unicode_argv(): """Uses shell32.GetCommandLineArgvW to get sys.argv as a list of Unicode strings. Versions 2.x of Python don't support Unicode in sys.argv on Windows, with the underlying Windows API instead replacing multi-byte characters with '?'. """ from ctypes import POINTER, byref, cdll, c_int, windll from ctypes.wintypes import LPCWSTR, LPWSTR GetCommandLineW = cdll.kernel32.GetCommandLineW GetCommandLineW.argtypes = [] GetCommandLineW.restype = LPCWSTR CommandLineToArgvW = windll.shell32.CommandLineToArgvW CommandLineToArgvW.argtypes = [LPCWSTR, POINTER(c_int)] CommandLineToArgvW.restype = POINTER(LPWSTR) cmd = GetCommandLineW() argc = c_int(0) argv = CommandLineToArgvW(cmd, byref(argc)) if argc.value > 0: # Remove Python executable and commands if present start = argc.value - len(sys.argv) return [argv[i] for i in xrange(start, argc.value)] sys.argv = win32_unicode_argv() 

Теперь, я использую это просто:

 import sys import win32_unicode_argv 

и с тех пор sys.argv представляет собой список строк Unicode. Модуль optparse Python, похоже, с удовольствием разбирает его, что здорово.

Работа с кодировками очень запутанна.

Я считаю, что если вы вводите данные через командную строку, они будут кодировать данные как независимо от вашей системной кодировки и не являются unicode. (Даже копирование / вставка должны делать это)

Поэтому должно быть правильно декодировать в Юникод, используя системную кодировку:

 import sys first_arg = sys.argv[1] print first_arg print type(first_arg) first_arg_unicode = first_arg.decode(sys.getfilesystemencoding()) print first_arg_unicode print type(first_arg_unicode) f = codecs.open(first_arg_unicode, 'r', 'utf-8') unicode_text = f.read() print type(unicode_text) print unicode_text.encode(sys.getfilesystemencoding()) 

запуск следующего выходного файла: Prompt> python myargv.py «ПК · ソ フ ト 申請書 08.09.24.txt»

 PC・ソフト申請書08.09.24.txt <type 'str'> <type 'unicode'> PC・ソフト申請書08.09.24.txt <type 'unicode'> ?日本語 

Если в «PC · ソ フ ト 申請書 08.09.24.txt» содержится текст «日本語». (Я закодировал файл как utf8, используя блокнот Windows, я немного озадачен тем, почему в печати при печати есть «?». Что-то связано с тем, как блокнот сохраняет utf8?)

Метод декодирования строк или встроенный unicode () может использоваться для преобразования кодировки в Юникод.

 unicode_str = utf8_str.decode('utf8') unicode_str = unicode(utf8_str, 'utf8') 

Кроме того, если вы работаете с закодированными файлами, вы можете использовать функцию codecs.open () вместо встроенного open (). Он позволяет определить кодировку файла и затем использовать данную кодировку для прозрачного декодирования содержимого в Юникоде.

Поэтому, когда вы вызываете content = codecs.open("myfile.txt", "r", "utf8").read() content content = codecs.open("myfile.txt", "r", "utf8").read() будет находиться в юникоде.

codecs.open: http://docs.python.org/library/codecs.html?#codecs.open

Если я скучаю-понимаю что-то, пожалуйста, дайте мне знать.

Если вы еще не рекомендуете читать статью Джоэля об Unicode и кодировке: http://www.joelonsoftware.com/articles/Unicode.html

Попробуй это:

 import sys print repr(sys.argv[1].decode('UTF-8')) 

Возможно, вам нужно заменить CP437 или CP1252 на UTF-8 . Вы должны иметь возможность вывести правильное имя кодировки из раздела реестра HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\CodePage\OEMCP

Командная строка может быть в кодировке Windows. Попробуйте декодировать аргументы в unicode объектах:

 args = [unicode(x, "iso-8859-9") for x in sys.argv] 
  • Рекомендуемая библиотека / инфраструктура python для локального веб-приложения?
  • Как заставить CMake выполнить некоторый скрипт после того, как он создает визуальное студийное решение
  • Python / Tkinter: мышь перетаскивает окно без границ, например. overridedirect (1)
  • Определение версий Windows
  • Django 1.9a1 __init__.py отображается в eclipse / PyDev, хотя его необходимо удалить (Windows)
  • Python не работает в командной строке git bash
  • Изменение размера шрифта при печати на экране
  • Сценарий Python, прокси и Microsoft Forefront - автоматическая аутентификация
  • Python - лучший язык программирования в мире.