Al canalizar la salida de un programa Python, el intérprete de Python se confunde acerca de la codificación y lo establece en Ninguno. Esto significa un programa como este:
# -*- coding: utf-8 -*-
print u"åäö"
funcionará bien cuando se ejecute normalmente, pero fallará con:
UnicodeEncodeError: el códec 'ascii' no puede codificar el carácter u '\ xa0' en la posición 0: el ordinal no está en el rango (128)
cuando se usa en una secuencia de tubería.
¿Cuál es la mejor manera de hacer que esto funcione al instalar tuberías? ¿Puedo decirle que use cualquier codificación del shell / sistema de archivos / lo que sea que esté usando?
Las sugerencias que he visto hasta ahora es modificar su site.py directamente, o codificar la codificación predeterminada utilizando este truco:
# -*- coding: utf-8 -*-
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
print u"åäö"
¿Hay una mejor manera de hacer que la tubería funcione?
chcp 65001
antes de ejecutar su script. Esto puede tener problemas, pero a menudo ayuda, y no requiere mucho tipeo (menos deset PYTHONIOENCODING=utf_8
).setx PYTHONENCODING utf-8
hacerlo permanente si desea guardar la escritura.Respuestas:
Su código funciona cuando se ejecuta en un script porque Python codifica la salida a cualquier codificación que esté utilizando su aplicación de terminal. Si está canalizando, debe codificarlo usted mismo.
Una regla general es: siempre use Unicode internamente. Decodifica lo que recibes y codifica lo que envías.
Otro ejemplo didáctico es un programa Python para convertir entre ISO-8859-1 y UTF-8, haciendo que todo esté en mayúscula.
Establecer la codificación predeterminada del sistema es una mala idea, porque algunos módulos y bibliotecas que utiliza pueden confiar en el hecho de que es ASCII. No lo hagas
fuente
sys.stdout
parece una forma más placentera.PYTHONIOENCODING
si está redirigiendo el stdout del script en Python 2.Primero, con respecto a esta solución:
No es práctico imprimir explícitamente con una codificación determinada cada vez. Eso sería repetitivo y propenso a errores.
Una mejor solución es cambiar
sys.stdout
al inicio de su programa, codificar con una codificación seleccionada. Aquí hay una solución que encontré en Python: ¿Cómo se elige sys.stdout.encoding? , en particular un comentario de "toka":fuente
def myprint(unicodeobj): print unicodeobj.encode('utf-8')
- automáticamente detecta la codificación del terminal mediante la inspecciónsys.stdout.encoding
, pero debe considerar el caso en el que se encuentraNone
( es decir, al redirigir la salida a un archivo) entonces necesita una función separada de todos modos.Puede intentar cambiar la variable de entorno "PYTHONIOENCODING" a "utf_8". He escrito una página sobre mi terrible experiencia con este problema .
Tl; dr de la publicación del blog:
te dio
fuente
sys.stdout = codecs.getwriter(encoding)(sys.stdout)
. Esto se puede hacer desde el programa python, por lo que el usuario no está obligado a establecer una variable env.PYTHONIOENCODING
funciona. El entorno del usuario define cómo se interpretan los bytes como texto . Su secuencia de comandos no debe asumir y dictar al entorno del usuario qué codificación de caracteres usar. Si Python no recoge la configuración automáticamente, entoncesPYTHONIOENCODING
se puede configurar para su script. No debería necesitarlo a menos que la salida se redirija a un archivo / tubería.hacer el trabajo, pero no puedo configurarlo en Python en sí ...
lo que podemos hacer es verificar si no está configurando y decirle al usuario que lo configure antes del script de llamada con:
Actualice para responder al comentario: el problema solo existe cuando se conecta a stdout. Probé en Fedora 25 Python 2.7.13
gato b.py
corriendo ./b.py
ejecutando ./b.py | Menos
fuente
sys.stdout.encoding
se establece automáticamente en función delLC_CTYPE
valor local.Tuve un problema similar la semana pasada . Fue fácil de arreglar en mi IDE (PyCharm).
Aquí estaba mi solución:
A partir de la barra de menú de PyCharm: Archivo -> Configuración ... -> Editor -> Codificación de archivos, luego configure: "Codificación IDE", "Codificación de proyecto" y "Codificación predeterminada para archivos de propiedades" TODOS para UTF-8 y ahora funciona como un encanto.
¡Espero que esto ayude!
fuente
Una versión desinfectada discutible de la respuesta de Craig McQueen.
Uso:
fuente
Podría "automatizarlo" con una llamada a:
Sí, es posible obtener un bucle infinito aquí si este "setenv" falla.
fuente
Solo pensé en mencionar algo aquí con lo que tuve que pasar mucho tiempo experimentando antes de finalmente darme cuenta de lo que estaba pasando. Esto puede ser tan obvio para todos aquí que no se han molestado en mencionarlo. ¡Pero me hubiera ayudado si lo hubieran hecho, así que en ese principio ...!
NB: Estoy usando Jython específicamente, v 2.7, así que posiblemente esto no se aplique a CPython ...
NB2: las dos primeras líneas de mi archivo .py aquí son:
El mecanismo de construcción de cadena "%" (AKA "operador de interpolación") también causa problemas ADICIONALES ... Si la codificación predeterminada del "entorno" es ASCII e intenta hacer algo como
No tendrá dificultades para ejecutar en Eclipse ... En una CLI de Windows (ventana de DOS) encontrará que la codificación es la página de códigos 850 (mi sistema operativo Windows 7) o algo similar, que puede manejar caracteres con acento europeo al menos, por lo que trabajaré
También funcionará.
Si, OTOH, dirige a un archivo desde la CLI, la codificación stdout será None, que será ASCII (en mi sistema operativo de todos modos), que no podrá manejar ninguna de las impresiones anteriores ... (codificación temida error).
Entonces podría pensar en redirigir su stdout usando
e intente ejecutar en la tubería CLI a un archivo ... Muy extrañamente, la impresión A anterior funcionará ... ¡Pero la impresión B anterior arrojará el error de codificación! Sin embargo, lo siguiente funcionará bien:
La conclusión a la que he llegado (provisionalmente) es que si una cadena que se especifica como una cadena Unicode que utiliza el prefijo "u" se envía al mecanismo de manejo de%, parece implicar el uso de la codificación de entorno predeterminada, independientemente de si ha configurado stdout para redirigir!
La forma en que las personas lidian con esto es una cuestión de elección. Me gustaría que un experto en Unicode dijera por qué sucede esto, si me equivoqué de alguna manera, cuál es la solución preferida para esto, si también se aplica a CPython , si sucede en Python 3, etc., etc.
fuente
"fréd"
es una secuencia de bytes y no una cadena Unicode, por lo que elcodecs.getwriter
contenedor lo dejará solo. Necesita un líderu
, ofrom __future__ import unicode_literals
.Me encontré con este problema en una aplicación heredada, y fue difícil identificar dónde se imprimió. Me ayudé con este truco:
Además de mi script, test.py:
Tenga en cuenta que esto cambia TODAS las llamadas a imprimir para usar una codificación, por lo que su consola imprimirá esto:
fuente
En Windows, tuve este problema muy a menudo al ejecutar un código Python desde un editor (como Sublime Text), pero no si lo ejecuto desde la línea de comandos.
En este caso, verifique los parámetros de su editor. En el caso de SublimeText, esto lo
Python.sublime-build
resolvió:fuente