Tengo muchos problemas de "no puedo codificar" y "no puedo decodificar" con Python cuando ejecuto mis aplicaciones desde la consola. Pero en Eclipse PyDev IDE, la codificación de caracteres predeterminada está establecida en UTF-8 , y estoy bien.
Busqué la configuración de la codificación predeterminada, y la gente dice que Python elimina la sys.setdefaultencoding
función en el inicio, y no podemos usarla.
Entonces, ¿cuál es la mejor solución para ello?
The best solution is to learn to use encode and decode correctly instead of using hacks.
Esto fue ciertamente posible con python2 a costa de recordar siempre hacerlo / usar constantemente su propia interfaz. Mi experiencia sugiere que esto se vuelve muy problemático cuando escribes código que quieres trabajar con python2 y python3.Respuestas:
Aquí hay un método más simple (pirateo) que le devuelve la
setdefaultencoding()
función que se eliminó desys
:(Nota para Python 3.4+:
reload()
está en laimportlib
biblioteca).Sin embargo, esto no es algo seguro : esto es obviamente un hack, ya que
sys.setdefaultencoding()
se elimina a propósito desys
cuando se inicia Python. Volver a habilitarlo y cambiar la codificación predeterminada puede romper el código que depende de que ASCII sea el predeterminado (este código puede ser de terceros, lo que generalmente haría que corregirlo sea imposible o peligroso).fuente
LC_CTYPE
(o en una aplicación, verificar si está configurado correctamente y abortar con un mensaje de error significativo).LC_CTYPE=C python -c 'import locale; print( locale.getpreferredencoding())'
Si obtiene este error cuando intenta canalizar / redirigir la salida de su script
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-5: ordinal not in range(128)
Simplemente exporte PYTHONIOENCODING en la consola y luego ejecute su código.
export PYTHONIOENCODING=utf8
fuente
LC_CTYPE
algo sensato en su lugar. También hace felices a todos los demás programas.PYTHONIOENCODING=utf8
no es el predeterminado. Esto hace que los guiones se rompan solo porqueLC_ALL=C
Set LC_CTYPE to something sensible instead
Esta es una sugerencia razonable. Esto no funciona tan bien cuando intenta distribuir código que solo funciona en el sistema de otra persona.C.utf8
entorno local para proporcionar C. glibc upstream más sensible está trabajando para agregarlo, por lo que quizás no deberíamos culpar a Python por respetar la configuración regional \ ...?A) Para controlar la
sys.getdefaultencoding()
salida:ascii
Luego
y
utf-16-be
Podrías poner tu sitecustomize.py más alto en tu
PYTHONPATH
.También te gustaría probar
reload(sys).setdefaultencoding
con @EOLB) Para controlar
stdin.encoding
ystdout.encoding
desea configurarPYTHONIOENCODING
:ascii ascii
Luego
utf-16-be utf-16-be
Finalmente: ¡puedes usar A) o B) o ambos!
fuente
from __future__ import unicode_literals
ver discusiónA partir de PyDev 3.4.1, la codificación predeterminada ya no se cambia. Vea este boleto para más detalles.
Para versiones anteriores, una solución es asegurarse de que PyDev no se ejecute con UTF-8 como codificación predeterminada. En Eclipse, ejecute la configuración de diálogo ("ejecutar configuraciones", si no recuerdo mal); puede elegir la codificación predeterminada en la pestaña común. Cámbielo a US-ASCII si desea tener estos errores 'temprano' (en otras palabras: en su entorno PyDev). También vea una publicación de blog original para esta solución .
fuente
Con respecto a python2 (y solo python2), algunas de las respuestas anteriores se basan en el uso del siguiente truco:
Se desaconseja usarlo (marque esto o esto )
En mi caso, viene con un efecto secundario: estoy usando las notebooks ipython, y una vez que ejecuto el código, la función 'imprimir' ya no funciona. Supongo que habría una solución, pero aún creo que usar el hack no debería ser la opción correcta.
Después de probar muchas opciones, la que funcionó para mí fue usar el mismo código en
sitecustomize.py
, donde ese fragmento de código debe ser . Después de evaluar ese módulo, la función setdefaultencoding se elimina de sys.Entonces, la solución es agregar el archivo
/usr/lib/python2.7/sitecustomize.py
del código:Cuando uso virtualenvwrapper, el archivo que edito es
~/.virtualenvs/venv-name/lib/python2.7/sitecustomize.py
.Y cuando lo uso con portátiles Python y conda, es
~/anaconda2/lib/python2.7/sitecustomize.py
fuente
Hay una publicación de blog perspicaz al respecto.
Ver https://anonbadger.wordpress.com/2015/06/16/why-sys-setdefaultencoding-will-break-code/ .
Parafraseo su contenido a continuación.
En Python 2, que no estaba tan fuertemente tipado con respecto a la codificación de cadenas, podría realizar operaciones en cadenas codificadas de manera diferente y tener éxito. Por ejemplo, lo siguiente volvería
True
.Eso se mantendría para cada cadena (normal, no prefijada) que se codificó
sys.getdefaultencoding()
, que se estableció de manera predeterminadaascii
, pero no en otras.La codificación predeterminada debía cambiarse en todo el sistema en
site.py
, pero no en otro lugar. Los hacks (también presentados aquí) para configurarlo en módulos de usuario fueron solo eso: hacks, no la solución.Python 3 cambió la codificación del sistema por defecto a utf-8 (cuando LC_CTYPE es compatible con Unicode), pero el problema fundamental se resolvió con el requisito de codificar explícitamente cadenas "byte" cada vez que se usan con cadenas Unicode.
fuente
Primero:
reload(sys)
y establecer una codificación predeterminada aleatoria con respecto a la necesidad de un flujo de terminal de salida es una mala práctica.reload
a menudo cambia cosas en sys que se han implementado en función del entorno, por ejemplo, sys.stdin / stdout streams, sys.excepthook, etc.Resolviendo el problema de codificación en stdout
La mejor solución que conozco para resolver el problema de codificación de
print
las cadenas unicode y más allá de asciistr
(por ejemplo, de literales) en sys.stdout es: cuidar un sys.stdout (objeto similar a un archivo) que sea capaz y opcionalmente tolerante con respecto a las necesidades:Cuando
sys.stdout.encoding
seaNone
por alguna razón, o no exista, o sea erróneamente falso o "menor" de lo que realmente es capaz el terminal o flujo stdout, intente proporcionar un.encoding
atributo correcto . Por fin reemplazándolosys.stdout & sys.stderr
por un objeto similar a un archivo de traducción.Cuando el terminal / flujo todavía no puede codificar todos los caracteres unicode que ocurren, y cuando no desea romperlos
print
solo por eso, puede introducir un comportamiento de codificar con reemplazar en el objeto similar a un archivo de traducción.Aquí un ejemplo:
Uso de literales de cadena simple más allá de ascii en código Python 2/2 + 3
Creo que la única buena razón para cambiar la codificación predeterminada global (solo a UTF-8) se refiere a una decisión del código fuente de la aplicación , y no debido a problemas de codificación de flujo de E / S: para escribir literales de cadena más allá de ASCII en el código sin ser forzado usar siempre el
u'string'
estilo de escape unicode. Esto se puede hacer de manera bastante consistente (a pesar de lo que dice el artículo de anonbadger ) cuidando una base de código fuente Python 2 o Python 2 + 3 que usa los literales de cadena simple ascii o UTF-8 de manera consistente, siempre que esas cadenas se sometan potencialmente en silencio conversión unicode y moverse entre módulos o potencialmente ir a stdout. Para eso, prefiere "# encoding: utf-8
"o ascii (sin declaración). Cambiar o descartar las bibliotecas que todavía dependen de una manera muy tonta fatalmente de los errores de codificación predeterminados de ascii más allá del chr # 127 (que es raro hoy en día).Y haga esto al inicio de la aplicación (y / o a través de sitecustomize.py) además del
SmartStdout
esquema anterior, sin usarreload(sys)
:De esta manera, los literales de cadena y la mayoría de las operaciones (excepto la iteración de caracteres) funcionan cómodamente sin pensar en la conversión unicode como si solo hubiera Python3. La E / S de archivos, por supuesto, siempre necesita un cuidado especial con respecto a las codificaciones, como sucede en Python3.
Nota: las cadenas simples se convierten implícitamente de utf-8 a unicode
SmartStdout
antes de convertirse a la secuencia de salida encontrando.fuente
Este es el enfoque que utilicé para producir código que fuera compatible con python2 y python3 y que siempre produjera salida utf8 . Encontré esta respuesta en otra parte, pero no recuerdo la fuente.
Este enfoque funciona reemplazando
sys.stdout
con algo que no es como un archivo (pero que solo usa cosas en la biblioteca estándar). Esto puede causar problemas para sus bibliotecas subyacentes, pero en el caso simple de que tenga un buen control sobre cómo se usa sys.stdout out a través de su marco, este puede ser un enfoque razonable.fuente
Esto solucionó el problema para mí.
fuente
Este es un truco rápido para cualquiera que esté (1) en una plataforma de Windows (2) ejecutando Python 2.7 y (3) molesto porque es una buena pieza de software (es decir, no está escrito por usted, por lo que no es un candidato inmediato para la impresión de codificación / decodificación) maniobras) no mostrará los "caracteres bastante unicode" en el entorno IDLE (Pythonwin imprime unicode bien), por ejemplo, los símbolos de lógica de primer orden que Stephan Boyer usa en la salida de su probador pedagógico en First Order Logic Prover .
No me gustó la idea de forzar una recarga del sistema y no pude lograr que el sistema cooperara con la configuración de variables de entorno como PYTHONIOENCODING (probé la variable de entorno directa de Windows y también la dejé en un sitio personalizado.py en paquetes de sitio como uno solo) liner = 'utf-8').
Entonces, si está dispuesto a hackear su camino hacia el éxito, vaya a su directorio IDLE, típicamente: "C: \ Python27 \ Lib \ idlelib" Localice el archivo IOBinding.py. Haga una copia de ese archivo y guárdelo en otro lugar para que pueda volver al comportamiento original cuando lo desee. Abra el archivo en idlelib con un editor (por ejemplo, IDLE). Vaya a esta área de código:
En otras palabras, comente la línea de código original después del ' intento ' que hacía que la variable de codificación fuera igual a locale.getdefaultlocale (porque eso le dará cp1252 que no desea) y, en su lugar, la fuerza bruta a 'utf-8 '(agregando la línea' encoding = 'utf-8 ' como se muestra).
Creo que esto solo afecta a la visualización IDLE en stdout y no a la codificación utilizada para los nombres de archivos, etc. (que se obtiene en el archivo anterior) Si tiene un problema con cualquier otro código que ejecute en IDLE más tarde, simplemente reemplace el archivo IOBinding.py con el archivo original no modificado.
fuente
Puede cambiar la codificación de todo su sistema operativo. En Ubuntu puedes hacer esto con
fuente