У меня есть следующий код Python 3.7 в импортированном пакете, который я не могу изменить, который считывает и декодирует имя системного компилятора, предоставленное disttools:
Код: Выделить всё
# subproc.py
import os
import sys
import locale
import subprocess
from distutils.ccompiler import new_compiler
ccompiler = new_compiler()
ccompiler.initialize()
cc = subprocess.check_output(f"{ccompiler.cc}", stderr=subprocess.STDOUT, shell=True)
encoding = os.device_encoding(sys.stdout.fileno()) or locale.getpreferredencoding()
print("Encoding:", encoding)
compiler_name = cc.decode(encoding).partition("\n")[0].strip()
print("Compiler name:", compiler_name)
Однако, когда я вызываю его с помощью subprocess.Popen(), os.device_encoding возвращает None вместо cp850 (он же utf-8), в результате чего программа по умолчанию использует кодировку Windows cp1242 (aka ), что затем приводит к тому, что cc.decode(encoding) вызывает ошибку UnicodeDecodeError: кодек 'charmap' не может декодировать байт 0x81 в позиции 62: символ соответствует .
Вот как я запускаю подпроцесс:
Код: Выделить всё
# call_subprocess.py
import subprocess
subprocess.Popen(
[
"python",
"C:/path/to/subproc.py",
],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
)
Насколько я понимаю, os.device_encoding(sys.stdout.fileno()) не может найти кодировку, поскольку подпроцесс выполняется в фоновом режиме, без терминала. Кроме того, Windows всегда будет предоставлять cp1242 при запросе с помощью locale.getpreferredencoding().
Поскольку я не могу редактировать код во внешнем пакете, есть ли способ вызвать подпроцесс, чтобы заставить любую из этих команд вернуть cp850?
Варианты, которые я пытался решить проблему:
- Явно установить кодировку в Popen:
Код: Выделить всё
subprocess.Popen( ... text=True, encoding="cp850", ) - Явно установите PYTHONIOENCODING в среде подпроцесса:
Код: Выделить всё
environ = os.environ.copy() environ['PYTHONIOENCODING'] = 'utf-8' ... subprocess.Popen( ... env=environ, encoding='utf-8', ) - Используйте subprocess.run() вместо subprocess.Popen()
- Различные комбинации приведенных выше решений.
[*]Подпроцесс использует неверную кодировку в Windows
[*]Ошибка кодирования, выполняемая в подпроцессе с захваченным вывод
[*]Изменение предпочтительной кодировки локали для самого компьютера -> Работает, но нежелательно, поскольку код должен быть исполняемым на разных машинах без индивидуальной настройки каждый раз.
Подробнее здесь: https://stackoverflow.com/questions/793 ... ing-decodi
Мобильная версия