Аргумент Python 3 (полу) не UTF-8 при передаче из Windows batch.cmd - PullRequest
0 голосов
/ 03 августа 2010

Когда я вызываю скрипт Python 3 из Windows batch.cmd, аргумент UTF-8 передается не как "UTF-8", а как последовательность байтов, каждый из которых интерпретируется Python как отдельные символы UTF-8.

Как я могу преобразовать строку аргумента Python 3 в предназначенное состояние UTF-8?
Вызывающий .cmd и вызываемый .py показаны ниже.

PS. Как я упоминаю в комментарии ниже, вызов u00FF.py "ÿ" напрямую из командной строки консоли Windows работает нормально. Проблема возникает только тогда, когда я вызываю u00FF.cmd через .cmd , и я ищу способ Python 3 для преобразования дважды кодированного аргумента UTF-8 обратно в "нормально" кодированный UTF -8 форма.

Теперь я включил здесь полный (и последний) тестовый код. Он немного длинный, но я надеюсь, что он достаточно ясно объясняет проблему.

Обновление: я видел, почему чтение файла "ÿ" было "двойным кодированием" ... Я читал файл UTF-8 в двоичном / байтовом режиме ... Я должен был использовать codecs.open('u00FF.arg', 'r', 'utf-8') вместо просто open('u00FF.arg','r') ... Я обновил неправильный код и вывод. Проблемы с кодовой страницей, похоже, сейчас являются единственной проблемой ...

Поскольку проблема с Python в основном решена, а проблема с кодовой страницей совершенно не зависит от Python, я разместил еще один вопрос, специфичный для кодовой страницы, на
Кодовая страница 850 работает, 65001 не работает! НЕТ ответа на «call foo.cmd». внутренние команды работают нормально.

:::::::::::::::::::   BEGIN .cmd BATCH FILE ::::::::::::::::::::
:: Windows Batch file (UTF-8 encoded, no BOM): "u00FF.cmd" 
   @echo ÿ>u00FF.arg
   @u00FF.py "ÿ"  
   @goto :eof  
:::::::::::::::::::   END OF .cmd BATCH FILE ::::::::::::::::::::

################### BEGIN .py SCRIPT #####################################  
    # -*- coding: utf-8 -*-

    import sys
    print ("""
    Unicode
    =======
        CodePoint U+00FF
        Character ÿ __Unicode Character 'LATIN SMALL LETTER Y WITH DIAERESIS'

    UTF-8 bytes
    ===========
        Hex: \\xC3 \\xBF
        Dec:  195  191
        Char:   Ã    ¿ __Unicode Character 'INVERTED QUESTION MARK'
                 \_______Unicode Character 'LATIN CAPITAL LETTER A WITH TILDE' 

    """)
    print("## ====================================================")
    print("## ÿ via hard-coding in this .py script itself ========")
    print("##")
    hard1s = "ÿ"
    hard1b = hard1s.encode('utf_8')
    print("hard1s: len", len(hard1s), " '" + hard1s + "'")
    print("hard1b: len", len(hard1b),        hard1b)
    for i in range(0,len(hard1s)):
        print("CodePoint[", i, "]", hard1s[i], "U+"+"{0:x}".upper().format(ord(hard1s[i])).zfill(4) )
    print('''         This is a single CodePoint for "ÿ" (as expected).''')
    print()
    print("## ====================================================")
    print("## ÿ read into this .py script from a UTF-8 file ======")
    print("##")
    import codecs
    file1 = codecs.open( 'u00FF.arg', 'r', 'utf-8' )
    file1s = file1.readline()
    file1s = file1s[:1] # remove \r
    file1b = file1s.encode('utf_8')
    print("file1s: len", len(file1s), " '" + file1s + "'")
    print("file1b: len", len(file1b),        file1b)
    for i in range(0,len(file1s)):
        print("CodePoint[", i, "]", file1s[i], "U+"+"{0:x}".upper().format(ord(file1s[i])).zfill(4) )
    print('''         This is a single CodePoint for "ÿ" (as expected).''')
    print()
    print("## ====================================================")
    print("## ÿ via sys.argv  from a call to .py  from a .cmd) ===")
    print("##")
    argv1s = sys.argv[1]
    argv1b = argv1s.encode('utf_8')
    print("argv1s: len", len(argv1s), " '" + argv1s + "'")
    print("argv1b: len", len(argv1b),        argv1b)
    for i in range(0,len(argv1s)):
        print("CodePoint[", i, "]", argv1s[i], "U+"+"{0:x}".upper().format(ord(argv1s[i])).zfill(4) )
    print('''         These 2 CodePoints are way off-beam,
                     even allowing for the "double-encoding" seen above.
                     The CodePoints are from an entirely different Unicode-Block.
                     This must be a Codepage issue.''')
    print()
################### END OF .py SCRIPT #####################################  

Вот вывод приведенного выше кода.

========================== BEGIN OUTPUT ================================
    C:\>u00FF.cmd
    Unicode
    =======
        CodePoint U+00FF
        Character ÿ __Unicode Character 'LATIN SMALL LETTER Y WITH DIAERESIS'

    UTF-8 bytes
    ===========
        Hex: \xC3 \xBF
        Dec:  195  191
        Char:   Ã    ¿ __Unicode Character 'INVERTED QUESTION MARK'
                 \_______Unicode Character 'LATIN CAPITAL LETTER A WITH TILDE'


    ## ====================================================
    ## ÿ via hard-coding in this .py script itself ========
    ##
    hard1s: len 1  'ÿ'
    hard1b: len 2 b'\xc3\xbf'
    CodePoint[ 0 ] ÿ U+00FF
                     This is a single CodePoint for "ÿ" (as expected).

    ## ====================================================
    ## ÿ read into this .py script from a UTF-8 file ======
    ##
    file1s: len 1  'ÿ'
    file1b: len 2 b'\xc3\xbf'
    CodePoint[ 0 ] ÿ U+00FF
                     This is a single CodePoint for "ÿ" (as expected

    ## ====================================================
    ## ÿ via sys.argv  from a call to .py  from a .cmd) ===
    ##
    argv1s: len 2  '├┐'
    argv1b: len 6 b'\xe2\x94\x9c\xe2\x94\x90'
    CodePoint[ 0 ] ├ U+251C
    CodePoint[ 1 ] ┐ U+2510
                     These 2 CodePoints are way off-beam,
                     even allowing for the "double-encoding" seen above.
                     The CodePoints are from an entirely different Unicode-Block.
                     This must be a Codepage issue.
========================== END OF OUTPUT ================================

Ответы [ 2 ]

3 голосов
/ 03 августа 2010

Пакетные файлы и кодировки - проблема привередливая.Прежде всего: пакетные файлы не имеют прямого способа указать кодировку, в которой они находятся, и cmd на самом деле не поддерживает пакетные файлы Unicode.Вы можете легко увидеть, что если вы сохраните командный файл с Unicode BOM или как UTF-16 - они выдадут ошибку.

То, что вы видите, когда вводите ÿ непосредственно в командную строку, таково, чтопри запуске команды Windows первоначально будет использовать командную строку в качестве Unicode (возможно, она была заранее преобразована из некоторой устаревшей кодировки, но в конце концов Windows использует Unicode).Таким образом, Python будет (надеюсь) всегда получать содержимое аргументов в Юникоде.

Однако, поскольку cmd имеет свое собственное мнение о кодовой странице (и вы никогда не говорили ей использовать UTF-8), UTF-8Строка, которую вы поместили в пакетный файл, не будет интерпретироваться как UTF-8, но вместо этого будет использоваться кодовая страница cmd по умолчанию (850 или 437, в вашем случае).

Вы можете принудительно установить UTF-8 с помощью chcp:

chcp 65001 > nul

Вы можете сохранить следующий файл как UTF-8 и попробовать его:

@echo off
chcp 850 >nul
echo ÿ
chcp 65001 >nul
echo ÿ

Имейте в виду, однако, что настройка chcp сохранится воболочка, если вы запустите пакет оттуда, что может сделать что-то странное.

1 голос
/ 03 августа 2010

Оболочка Windows использует определенную кодовую страницу (см. CHCP вывод команды).Вам необходимо конвертировать кодовую страницу Windows в utf-8.См. iconv модуль или decode() / encode()

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...