У меня есть рабочий базовый код, который будет выполнять команды в bash.Но все падает на окнах при использовании Unicode-строк.Вот тестовый пример:
cd /tmp
cat <<EOF > test.py
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
import sys
from subprocess import Popen, PIPE
ON_POSIX = 'posix' in sys.builtin_module_names
def execute_bash(cmd):
command = ["bash", "-c", cmd]
p = Popen(command, stdin=PIPE, stdout=PIPE, stderr=PIPE,
close_fds=ON_POSIX, universal_newlines=False)
return p.communicate()
print(repr(execute_bash('echo hello'))) ## works fine
print(repr(execute_bash('echo à'))) ## fails
EOF
python test.py
Я ожидаю получить этот вывод (это работает с Linux):
(b'hello\n', b'')
(b'\xc3\xa0\n', b'')
Но иметь:
('hello\n', '')
('', "bash: $'echo \\303\\203\\302\\240': command not found\n")
Итак, мои вопросы:
- почему это ?и
- как мне сделать реализацию
execute_bash
, которая бы работала для любого кода в windows ?
Вот еще несколько сведений о том, чтоЯ уже изучил, и то, что мне, вероятно, не хватает для решения этой проблемы:
Я использую python 3.7
, и я знаю несколько проблем с окнами и кодировками, которые я пытаюсь исключить из этого примера,Я знаю, что реализация CPython Popen
использует CreateProcessW(..)
начиная с python 3
и что мы должны иметь возможность отправлять прямые командные строки Unicode.Мне также известно о существовании subprocess.list2cmdline(..)
, которое сгладит аргументы в одну строку юникода для подачи в CreateProcessW(..)
.Я вроде знаю, что в мире Windows разбор командной строки должен обрабатываться приложением ... но вот где мои знания ограничены: какое приложение получает полную строку командной строки?почему не удается правильно обработать строку в юникоде?
Обратите внимание, что при выполнении в командной строке cmd.exe
возникает та же проблема.
T:\>bash -c "echo hello"
hello
T:\>bash -c "echo à"
bash: $'echo \303\240': command not found
Примечание: \303\240
isвосьмеричное для кодировки utf-8 à
.