Как `[System.Console]:: OutputEncoding/InputEncoding` с Python?

В Powershell v5, Windows 8.1, Python 3. Почему это не удается и как исправить?

[system.console]::InputEncoding = [System.Text.Encoding]::UTF8; 
[system.console]::OutputEncoding = [System.Text.Encoding]::UTF8; 
chcp; 
"import sys
print(sys.stdout.encoding)
print(sys.stdin.encoding)
sys.stdout.write(sys.stdin.readline())
" | 
sc test.py -Encoding utf8; 
[char]0x0422+[char]0x0415+[char]0x0421+[char]0x0422+"`n" | py -3 test.py

печатает:

Active code page: 65001
cp65001
cp1251
п»ї????

Ответы

Ответ 1

Вы передаете данные в Python; в этот момент Python stdin больше не привязан к TTY (вашей консоли) и не догадается, что такое кодировка. Вместо этого используется локаль системы по умолчанию; в вашей системе, что cp1251 (кодовая страница на основе Windows Latin-1).

Установите переменную окружения PYTHONIOENCODING для переопределения:

PYTHONIOENCODING
Если он установлен перед запуском интерпретатора, он переопределяет кодировку, используемую для stdin/stdout/stderr, в синтаксисе encodingname:errorhandler. Обе части encodingname и :errorhandler являются необязательными и имеют то же значение, что и в str.encode().

PowerShell, похоже, не поддерживает переменные окружения командной строки, как это делают оболочки UNIX; проще всего просто установить переменную:

Set-Item Env:PYTHONIOENCODING "UTF-8"

или даже

Set-Item Env:PYTHONIOENCODING "cp65001"

поскольку кодовая страница Windows UTF-8, по-видимому, не совсем UTF-8, в зависимости от версии Windows, а также от перенаправления или переадресации труб.

Ответ 2

Почему бы не вставить CPython в powershell?! CPython так просто вставлять, и powershell очень хорош REPL для играть с объектами .NET и COM. Вот простое введение в pythonnet из PowerShell. Обратите внимание, как кодирование автоматически распространяется с powershell на python.

Windows PowerShell
Copyright (C) 2015 Microsoft Corporation. All rights reserved.

PS C:\Users\denfromufa> [system.console]::InputEncoding = [System.Text.Encoding]::UTF8;
PS C:\Users\denfromufa> [system.console]::OutputEncoding = [System.Text.Encoding]::UTF8;
PS C:\Users\denfromufa> [Reflection.Assembly]::LoadFile("C:\Python\Miniconda3_64b\Lib\site-packages\Python.Runtime.dll")


GAC    Version        Location
---    -------        --------
False  v4.0.30319     C:\Python\Miniconda3_64b\Lib\site-packages\Python.Runtime.dll


PS C:\Users\denfromufa> $gil = [Python.Runtime.Py]::GIL()
PS C:\Users\denfromufa> $sys=[Python.Runtime.Py]::Import("sys")
PS C:\Users\denfromufa> $sys.stdin.encoding.ToString()
cp65001
PS C:\Users\denfromufa> $sys.stdout.encoding.ToString()
cp65001
PS C:\Users\denfromufa> $gil.Dispose()
PS C:\Users\denfromufa> [Python.Runtime.PythonEngine]::Shutdown()
PS C:\Users\denfromufa>

[EDIT]

Вот пакет snek, выпущенный одним из разработчиков powershell для встраивания Python в powershell:

https://github.com/adamdriscoll/snek