Entendiendo Python Unicode y el terminal de Linux

Tengo un script de Python que escribe algunas cadenas con encoding UTF-8. En mi script, estoy utilizando principalmente la función str() para convertir en una cadena. Se ve así:

 mystring="this is unicode string:"+japanesevalues[1] #japanesevalues is a list of unicode values, I am sure it is unicode print mystring 

No uso el terminal Python, solo el terminal estándar Linux Red Hat x86_64. Configuro el terminal para que salga los caracteres utf8.

Si ejecuto esto:

 #python myscript.py this is unicode string: カラダーズ ソフィー 

Pero si hago eso:

 #python myscript.py > output 

Tengo el error típico:

 UnicodeEncodeError: 'ascii' codec can't encode characters in position 253-254: ordinal not in range(128) 

¿Porqué es eso?

El terminal tiene un conjunto de caracteres, y Python sabe qué es ese conjunto de caracteres, por lo que descodificará automáticamente sus cadenas Unicode a la encoding de bytes que utiliza el terminal, en su caso UTF-8.

Pero cuando redirecciona, ya no está utilizando el terminal. Ahora solo estás usando una tubería Unix. Esa canalización de Unix no tiene un conjunto de caracteres, y Python no tiene forma de saber qué encoding desea ahora, por lo que volverá a un conjunto de caracteres predeterminado. Ha marcado su pregunta con “Python-3.x” pero su syntax de print es Python 2, así que sospecho que en realidad está usando Python 2. Y luego su sys.getdefaultencoding() es generalmente 'ascii' , y en su caso es definitivamente así Y, por supuesto, no puede codificar caracteres japoneses como ASCII, por lo que recibe un error.

Lo mejor que puedes hacer cuando usas Python 2 es codificar la cadena con UTF-8 antes de imprimirla. Luego, la redirección funcionará y el archivo resultante será UTF-8. Sin embargo, eso significa que no funcionará si su terminal es otra cosa, pero puede obtener la encoding del terminal desde sys.stdout.encoding y usarla (será Ninguno al redirigir bajo Python 2).

En Python 3, su código debería funcionar tal como está, excepto que necesita cambiar print mystring de print(mystring) para print(mystring) .

Si sale al terminal, Python puede examinar el valor de $LANG para elegir un juego de caracteres. Todas las apuestas están apagadas si redireccionas.