Кодировка команд подпроцесса - PullRequest
1 голос
/ 23 октября 2019

Я сейчас перевожу скрипт из Perl в Python3 (3.6.5). Is работает на Windows Server 2016. Сценарий создает командную строку с аргументами и выполняет созданную строку с subprocess.check_output. Один из параметров аргумента называется -location:"my street". Местоположение может содержать специальные символы, такие как умлаут (äöß) или (ŠŠ).

Когда я запускаю скрипт Perl, специальные символы правильно передаются приложению. Когда я запускаю скрипт Python, специальные символы заменяются на вопросительные знаки в приложении. Я думаю, что вызываемому приложению нужна строка аргумента в кодировке UTF-8.

Скрипт Perl работает в режиме UTF-8

use UTF8;
binmode( STDOUT, ":utf-8" );

Скрипт Python создается с PyCharm, закодированным в UTF-8. и первая строка скрипта содержит

# -*- coding: utf-8 -*-

Я попытался несколько вещей установить кодировку UTF-8 для аргументов подпроцесса, но это не сработало. Я использовал procmon.exe для сравнения вызова приложения между скриптами Perl и Python. Что я вижу, так это то, что командная строка, которая отображается для вызова подпроцесса Python в procmon, доступна для чтения. Работающий Perl не вызывает. Строка местоположения ищет скрипт perl в procmon выглядит следующим образом:

-location:"HQ/äöööStraße".

Код Perl выглядит следующим образом:

$command = "C:\\PROGRAM FILES\\Application\\bin\\cfg.exe"
$operand = "-modify -location:123á456ß99"
$result  = `$command $operand`;

Код Python выглядиткак это:

# -*- coding: utf-8 -*-
import subprocess
result = subprocess.check_output(['C:\\PROGRAM FILES\\Application\\bin\\cfg.exe', "-modify", "-location:123á456ß99"], shell=False, stderr=subprocess.STDOUT)

Есть идеи, что я должен сделать, чтобы аргументы Python правильно передавались в приложение?

Ответы [ 2 ]

1 голос
/ 23 октября 2019

В Python 3.3+ вы можете отдельно указать, что вы ожидаете текст в определенной кодировке. Ключевое слово аргумент universal_newlines=True было переименовано в 3.7 в более точное и прозрачное text=True.

Это ключевое слово в основном гласит «просто используйте любую кодировку по умолчанию в моей системе» (так что в основном UTF-8 на любом разумномсовременный, за исключением Windows, где вы получаете некоторое злодеяние Ктулху из пропасти кодовая страница системы по умолчанию).

При отсутствии этого ключевого слова подпроцессы получают и возвращают bytes в Python 3.

Конечно, если вы знаете кодировку, вы также можете отдельно .decode() bytes получить обратно.

Если вы знаете кодировку, вероятно, полезно использовать encoding= аргумент ключевого слова (даже если вы предполагаете, что это также системная кодировка; это было добавлено в Python 3.6).

response = subprocess.check_output([...], text=True)
response = subprocess.check_output([...], encoding='utf-8')
response = subprocess.check_output([...]).decode('utf-8')
0 голосов
/ 05 ноября 2019

Хитрость для запуска скрипта состоит в том, чтобы закодировать аргументы в 'utf8', а затем декодировать их в 'ansi'.

command = r'C:\PROGRAM FILES\Application\bin\cfg.exe'
argument = ["-modify", "-location:123á456ß99"]

argument_ansi = []
for x in argument:
    argument_ansi.append(x.encode('utf-8').decode('ansi', 'replace'))
cmd = [command]
cmd.extend(argument_ansi)
result = subprocess.check_output(cmd, shell=False, encoding="utf-8", universal_newlines=True)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...