Python, Unicode y la consola de Windows
Cuando intento imprimir una cadena Unicode en una consola de Windows, obtengo un error UnicodeEncodeError: 'charmap' codec can't encode character ....
. Asumo que esto se debe a que la consola de Windows no acepta caracteres de solo Unicode. ¿Cuál es la mejor manera de evitar esto? ¿Hay alguna manera de hacer que Python imprima automáticamente un ?
en lugar de fallar en esta situación?
Edit: Estoy usando Python 2.5.
Nota: @LasseV.La respuesta de Karlsen con la marca de verificación es algo anticuada (de 2008). Por favor, utilice el soluciones / respuestas / sugerencias a continuación con cuidado!!
@La respuesta jfsebastiana es más relevante a partir de hoy (6 de enero de 2016).
13 answers
Nota: Esta respuesta está un poco desactualizada (de 2008). Por favor, utilice la solución a continuación con cuidado!!
Aquí hay una página que detalla el problema y una solución (busque en la página el texto Wrapping sys.stdout en una instancia):
Aquí hay un extracto de código de esa página:
$ python -c 'import sys, codecs, locale; print sys.stdout.encoding; \
sys.stdout = codecs.getwriter(locale.getpreferredencoding())(sys.stdout); \
line = u"\u0411\n"; print type(line), len(line); \
sys.stdout.write(line); print line'
UTF-8
<type 'unicode'> 2
Б
Б
$ python -c 'import sys, codecs, locale; print sys.stdout.encoding; \
sys.stdout = codecs.getwriter(locale.getpreferredencoding())(sys.stdout); \
line = u"\u0411\n"; print type(line), len(line); \
sys.stdout.write(line); print line' | cat
None
<type 'unicode'> 2
Б
Б
Hay más información en esa página, bien vale la pena leerla.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-04 17:18:53
Actualizar: Python 3.6 implementa PEP 528: Cambiar la codificación de la consola de Windows a UTF-8: la consola predeterminada en Windows ahora aceptará todos los caracteres Unicode. Internamente, utiliza la misma API Unicode que el paquete win-unicode-console
mencionado a continuación. print(unicode_string)
debería funcionar ahora.
Obtengo un error
UnicodeEncodeError: 'charmap' codec can't encode character...
.
El error significa que los caracteres Unicode que está tratando de imprimir no se pueden representar codificación de caracteres de consola actual (chcp
). La página de código es a menudo codificación de 8 bits como cp437
que puede representar sólo ~0x100 caracteres de ~1M caracteres Unicode:
>>> u"\N{EURO SIGN}".encode('cp437') Traceback (most recent call last): ... UnicodeEncodeError: 'charmap' codec can't encode character '\u20ac' in position 0: character maps to
Asumo que esto se debe a que la consola de Windows no acepta caracteres solo Unicode. ¿Cuál es la mejor manera de evitar esto?
La consola de Windows acepta caracteres Unicode e incluso puede mostrarlos (solo BMP) si la fuente correspondiente está configurada. WriteConsoleW()
API debe ser se usa como se sugiere en la respuesta de@Daira Hopwood . Se puede llamar de forma transparente, es decir, no es necesario y no debe modificar sus scripts si utiliza win-unicode-console
paquete :
T:\> py -mpip install win-unicode-console
T:\> py -mrun your_script.py
Ver ¿Cuál es el problema con Python 3.4, Unicode, diferentes lenguajes y Windows?
¿Hay alguna manera de que pueda hacer Python imprimir automáticamente un
?
en lugar de fallar en esta situación?
Si es suficiente para reemplazar todos los caracteres no codificables con ?
en su caso, entonces usted podría establecer PYTHONIOENCODING
envvar:
T:\> set PYTHONIOENCODING=:replace
T:\> python3 -c "print(u'[\N{EURO SIGN}]')"
[?]
En Python 3.6+, la codificación especificada por PYTHONIOENCODING
envvar se ignora para los buffers de consola interactivos a menos que PYTHONLEGACYWINDOWSIOENCODING
envvar se establezca en una cadena no vacía.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:10:44
A pesar de las otras respuestas que suenan plausibles que sugieren cambiar la página de códigos a 65001, eso no funciona. (Además, cambiar la codificación predeterminada usando sys.setdefaultencoding
es no es una buena idea.)
Vea esta pregunta para detalles y código que funciona.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:26:33
Si no está interesado en obtener una representación confiable de los caracteres malos, puede usar algo como esto(trabajando con python >= 2.6, incluyendo 3.x):
from __future__ import print_function
import sys
def safeprint(s):
try:
print(s)
except UnicodeEncodeError:
if sys.version_info >= (3,):
print(s.encode('utf8').decode(sys.stdout.encoding))
else:
print(s.encode('utf8'))
safeprint(u"\N{EM DASH}")
El(los) carácter (s) malo (s) en la cadena se convertirá (n) en una representación que se puede imprimir en la consola de Windows.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-05-19 18:48:28
El siguiente código hará que Python salga a la consola como UTF-8 incluso en Windows.
La consola mostrará bien los caracteres en Windows 7, pero en Windows XP no los mostrará bien, pero al menos funcionará y lo más importante es que tendrá una salida consistente de su script en todas las plataformas. Podrás redirigir la salida a un archivo.
El siguiente código fue probado con Python 2.6 en Windows.
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import codecs, sys
reload(sys)
sys.setdefaultencoding('utf-8')
print sys.getdefaultencoding()
if sys.platform == 'win32':
try:
import win32console
except:
print "Python Win32 Extensions module is required.\n You can download it from https://sourceforge.net/projects/pywin32/ (x86 and x64 builds are available)\n"
exit(-1)
# win32console implementation of SetConsoleCP does not return a value
# CP_UTF8 = 65001
win32console.SetConsoleCP(65001)
if (win32console.GetConsoleCP() != 65001):
raise Exception ("Cannot set console codepage to 65001 (UTF-8)")
win32console.SetConsoleOutputCP(65001)
if (win32console.GetConsoleOutputCP() != 65001):
raise Exception ("Cannot set console output codepage to 65001 (UTF-8)")
#import sys, codecs
sys.stdout = codecs.getwriter('utf8')(sys.stdout)
sys.stderr = codecs.getwriter('utf8')(sys.stderr)
print "This is an Е乂αmp١ȅ testing Unicode support using Arabic, Latin, Cyrillic, Greek, Hebrew and CJK code points.\n"
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-01-12 20:45:44
Como la respuesta de Giampaolo Rodolà, pero aún más sucia: Realmente, realmente tengo la intención de pasar mucho tiempo (pronto) entendiendo todo el tema de las codificaciones y cómo se aplican a las consolas Windoze,
Por el momento solo quería sthg, lo que significaría que mi programa NO se BLOQUEARÍA, y lo entendí ... y también que no implicó importar demasiados módulos exóticos (en particular, estoy usando Jython, por lo que la mitad del tiempo un módulo de Python resulta no ser disponible).
def pr(s):
try:
print(s)
except UnicodeEncodeError:
for c in s:
try:
print( c, end='')
except UnicodeEncodeError:
print( '?', end='')
NB "pr" es más corto para escribir que "print" (y bastante más corto para escribir que "safeprint")...!
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-09 22:14:15
Para Python 2 intente:
print unicode(string, 'unicode-escape')
Para Python 3 intente:
import os
string = "002 Could've Would've Should've"
os.system('echo ' + string)
O prueba win-unicode-console:
pip install win-unicode-console
py -mrun your_script.py
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-17 05:07:50
La causa de su problema es NO la consola Win no está dispuesta a aceptar Unicode (ya que lo hace ya que supongo que Win2k por defecto). Es la codificación predeterminada del sistema. Pruebe este código y vea lo que le da:
import sys
sys.getdefaultencoding()
Si dice ascii, ahí está tu causa ;-) Tienes que crear un archivo llamado sitecustomize.py y lo puse bajo python path (lo puse bajo / usr / lib/python2. 5 / site-packages, pero eso es diferente en Win - es c:\python\lib\site-packages o algo así), con el siguiente contenido:
import sys
sys.setdefaultencoding('utf-8')
Y tal vez desee especificar la codificación en sus archivos también:
# -*- coding: UTF-8 -*-
import sys,time
Editar: se puede encontrar más información en excellent the Dive into Python book
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-12-04 01:52:54
Algo relacionado con la respuesta de J. F. Sebastian, pero más directo.
Si tiene este problema al imprimir en la consola / terminal, haga lo siguiente:
>set PYTHONIOENCODING=UTF-8
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-16 07:53:43
Python 3.6 windows7: Hay varias maneras de lanzar un python que podría utilizar la consola python (que tiene un logotipo de python en él) o la consola de Windows (está escrito cmd.exe en él).
No pude imprimir caracteres utf8 en la consola de Windows. Imprimir caracteres utf-8 me arroja este error:
OSError: [winError 87] The paraneter is incorrect
Exception ignored in: (_io-TextIOwrapper name='(stdout)' mode='w' ' encoding='utf8')
OSError: [WinError 87] The parameter is incorrect
Después de intentar y no entender la respuesta anterior descubrí que era solo un problema de configuración. Haga clic derecho en la parte superior de las ventanas de la consola cmd, en la pestaña font
chose consola lucida.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-11 20:08:34
TL; DR:
print(yourstring.encode('ascii','replace'));
Me encontré con esto yo mismo, trabajando en un bot de Twitch chat (IRC). (Python 2.7 latest)
Quería analizar los mensajes de chat para responder...
msg = s.recv(1024).decode("utf-8")
Pero también imprímalos de forma segura en la consola en un formato legible por humanos:
print(msg.encode('ascii','replace'));
Esto corrigió el problema de los errores de lanzamiento del bot UnicodeEncodeError: 'charmap'
y reemplazó los caracteres unicode con ?
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-01 15:52:05
James Sulak preguntó,
¿Hay alguna manera de hacer que Python imprima automáticamente a ? en lugar de fallar en esta situación?
Otras soluciones recomiendan que intentemos modificar el entorno Windows o reemplazar la función print()
de Python. La respuesta a continuación se acerca más al cumplimiento de la solicitud de Sulak.
Bajo Windows 7, Python 3.5 se puede hacer para imprimir Unicode sin lanzar un UnicodeEncodeError
de la siguiente manera:
En lugar de:
print(text)
sustituir:
print(str(text).encode('utf-8'))
En lugar de lanzar una excepción, Python ahora muestra caracteres Unicode no imprimibles como \xNN códigos hexadecimales, por ejemplo:
Halmalo n \ xe2 \ x80\x99\xc3 \ xa9tait plus qu\xe2\x80 \ x99un point noir
En lugar de
Halmalo n'était plus qu'un point noir
Concedido, el último es preferible ceteris paribus, pero por lo demás el primero es completamente preciso para los mensajes de diagnóstico. Porque muestra Unicode como valores literales de bytes el primero también puede ayudar en el diagnóstico de problemas de codificación / decodificación.
Nota: La llamada str()
anterior es necesaria porque de lo contrario encode()
hace que Python rechace un carácter Unicode como una tupla de números.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-24 16:19:05
Simplemente ingrese este código en la línea de comandos antes de ejecutar el script python:
chcp 65001 & set PYTHONIOENCODING=utf-8
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-10-02 22:11:03