Как сообщить Python, что sys.argv находится в Unicode?

Вот небольшая программа:

import sys

f = sys.argv[1]
print type(f)
print u"f=%s" % (f)

Вот мой запуск программы:

$ python x.py 'Recent/רשימת משתתפים.LNK'
<type 'str'>
Traceback (most recent call last):
  File "x.py", line 5, in <module>
    print u"f=%s" % (f)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xd7 in position 7: ordinal not in range(128)
$ 

Проблема заключается в том, что sys.argv [1] думает, что он получает строку ascii, которую он не может преобразовать в Unicode. Но я использую Mac с полным Unicode-терминалом, поэтому x.py фактически получает строку Unicode. Как сообщить Python, что sys.argv [] является Unicode, а не Ascii? В противном случае, как преобразовать ASCII (который имеет unicode внутри него) в Unicode? Очевидные преобразования не работают.

Ответ 1

Ошибка UnicodeDecodeError, которую вы видите, связана с тем, что вы смешиваете строку Unicode u"f=%s" и sys.argv[1] bytestring:

  • оба байта:

    $ python -c'import sys; print "f=%s" % (sys.argv[1],)' 'Recent/רשימת משתתפים'
    

    Это пропускает байты прозрачно с/на ваш терминал. Он работает для любой кодировки.

  • Оба Unicode:

    $ python -c'import sys; print u"f=%s" % (sys.argv[1].decode("utf-8"),)' 'Rec..
    

    Здесь вы должны заменить 'utf-8' на кодировку, используемую вашим терминалом. Вы можете использовать sys.getfilesystemencoding() здесь, если терминал не поддерживает Unicode.

Обе команды производят один и тот же вывод:

f=Recent/רשימת משתתפים

В общем, вы должны как можно скорее преобразовать bytestrings, которые считаете текстом в Unicode.

Ответ 2

sys.argv = map(lambda arg: arg.decode(sys.stdout.encoding), sys.argv)

или вы можете выбрать кодировку из locale.getdefaultlocale()[1]

Ответ 3

Параметры командной строки передаются в Python в виде строки байта, используя кодировку, используемую в оболочке, используемой для запущенного Python. Таким образом, нет возможности передать параметры командной строки в Python как строку юникода, отличную от того, чтобы самостоятельно преобразовывать параметры в юникод внутри вашего приложения.

Ответ 4

  • sys.argv никогда не "в Юникоде"; он кодируется наверняка, но Unicode не является кодировкой, а представляет собой набор кодовых точек (чисел), где каждый номер однозначно представляет символ. http://www.unicode.org/standard/WhatIsUnicode.html

  • Перейдите в Terminal.app > Terminal > Предпочтения > Настройки > Кодировка символов и выберите UTF-8 из раскрывающегося списка.

  • Кроме того, Python по умолчанию, поставляемый с Mac OS X, имеет один недостаток в отношении Unicode: его по умолчанию используют устаревший UCS-2; см. http://webamused.wordpress.com/2011/01/31/building-64-bit-python-python-org-using-ucs-4-on-mac-os-x-10-6-6-snow-leopard/

Ответ 5

попробуйте либо:

f = sys.argv[1].decode('utf-8')

или

f = unicode(sys.argv[1], 'utf-8')