2014-09-03 10 views
5

Ho un programma nativo scritto in Python che si aspetta il suo input su stdin. Come semplice esempio,Come convogliare Unicode in un'applicazione nativa in PowerShell

#!python3 
import sys 
with open('foo.txt', encoding='utf8') as f: 
    f.write(sys.stdin.read()) 

Voglio essere in grado di passare un (PowerShell) stringa da questo programma come input standard. Python prevede il suo input standard nella codifica specificata in $env:PYTHONIOENCODING, che in genere verrà impostato su UTF8 (in modo che non venga rilevato alcun errore di codifica).

Ma non importa quello che faccio, i personaggi vengono corrotti. Ho cercato in rete e ho trovato suggerimenti per cambiare [Console]::InputEncoding/[Console]::OutputEncoding o per utilizzare chcp, ma niente sembra funzionare.

Ecco il mio test di base:

PS >[Console]::OutputEncoding.EncodingName 
Unicode (UTF-8) 
PS >[Console]::InputEncoding.EncodingName 
Unicode (UTF-8) 
PS >$env:PYTHONIOENCODING 
utf-8 
PS >python -c "print('\N{Euro sign}')" | python -c "import sys; print(sys.stdin.read())" 
´╗┐? 

PS >chcp 1252 
Active code page: 1252 
PS >python -c "print('\N{Euro sign}')" | python -c "import sys; print(sys.stdin.read())" 
? 

PS >chcp 65001 
Active code page: 65001 
PS >python -c "print('\N{Euro sign}')" | python -c "import sys; print(sys.stdin.read())" 
? 

Come posso risolvere questo problema?

Non riesco nemmeno a spiegare cosa sta succedendo qui. Fondamentalmente, voglio il test (python -c "print('\N{Euro sign}')" | python -c "import sys; print(sys.stdin.read())") per stampare un simbolo dell'euro. E per capire perché, devo fare tutto il necessario per farlo funzionare :-) (Perché allora posso tradurre quella conoscenza nel mio reale scenario, che è quello di essere in grado di scrivere pipeline funzionanti di programmi Python che don ' si interrompe quando incontrano caratteri Unicode).

+0

Hai provato a impostare '$ OutputEncoding'? –

+0

Ancora peggio: '' '> $ OutputEncoding = [Text.Encoding] :: UTF8 > $ env: PYTHONIOENCODING =" utf-8 " > python -c" print ('\ N {Euro sign}') "| python -c "import sys; print (sys.stdin.read())" ∩╗┐╬ô├⌐┬╝''' (Mi scuso per la formattazione, non riesco a ottenere newlines in un commento ...) –

+0

Ah, ma se I * anche * imposta [Console] :: OutputEncoding su UTF8, sembra funzionare! Puoi spiegare perché? Non sono chiaro perché devo impostare il valore due volte ... –

risposta

3

Grazie a mike z, i seguenti lavori:

$OutputEncoding = [Console]::OutputEncoding = (new-object System.Text.UTF8Encoding $false) 
$env:PYTHONIOENCODING = "utf-8" 
python -c "print('\N{Euro sign}')" | python -c "import sys; print(sys.stdin.read())" 

Il new-object è necessario per ottenere una codifica UTF-8 senza BOM. Sembra che sia necessario impostare la variabile $OutputEncoding e [Console]::OutputEncoding.

Non riesco ancora a comprendere appieno la differenza tra i due valori di codifica e perché li avresti mai impostati in modo diverso (che sembra essere l'impostazione predefinita).