2008-08-07 23 views
99

Cuando intento imprimir una cadena Unicode en una consola de Windows, aparece un error UnicodeEncodeError: 'charmap' codec can't encode character ..... Supongo que esto se debe a que la consola de Windows no acepta caracteres de Unicode solamente. ¿Cuál es la mejor manera de evitar esto? ¿Hay alguna manera en que pueda hacer que Python imprima automáticamente un ? en lugar de fallar en esta situación?Python, Unicode y la consola de Windows

Edit: Estoy usando Python 2.5.


Nota: @ respuesta LasseV.Karlsen con la marca de verificación es una especie de obsoleta (de 2008). Por favor, use las soluciones/respuestas/sugerencias a continuación con cuidado!

@JFSebastian answer es más relevante a partir de hoy (6 de enero de 2016).

+3

relacionados: http: // errores. python.org/issue1602 – jfs

+0

¿En qué versión de Python estás? He visto referencias que esto se rompió en 2.4.3 y se arregló en 2.4.4. – Stu

+0

marque [this] (http://stackoverflow.com/q/39528462/5284370) fuera. – Soorena

Respuesta

29

Nota: Esta respuesta está desactualizada (desde 2008). Por favor, use la solución a continuación con cuidado!


Aquí hay una página que detalla el problema y una solución (buscar en la página para el ajuste de texto sys.stdout en una instancia):

PrintFails - Python Wiki

Aquí está un extracto del código 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, vale la pena leerla.

+7

El enlace está muerto y la esencia de la respuesta no se ha citado. -1 – 0xC0000022L

+0

El enlace funciona ahora, pero no está muy claro lo que sugiere. – Kugel

+1

Cuando intento el consejo dado sobre el ajuste 'sys.stdout', imprime las cosas incorrectas. Por ejemplo, 'u '\ u2013'' se convierte en' û' en lugar de en-dash. – user2357112

0

La causa de su problema es NOT la consola de Win no está dispuesta a aceptar Unicode (ya que hace esto porque supongo que es Win2k por defecto). Es la codificación predeterminada del sistema. Prueba este código y ver lo que le da:

import sys 
sys.getdefaultencoding() 

si dice ascii, no su causa ;-) Tienes que crear un archivo llamado sitecustomize.py y ponerlo en la ruta de Python (I ponerlo bajo /usr/lib/python2.5/site-packages, pero que se diferen en Win - es c: \ Python \ lib \ sitio-paquetes o algo así), con el siguiente contenido:

import sys 
sys.setdefaultencoding('utf-8') 

y tal vez Es posible que desee especificar también la codificación en sus archivos:

# -*- coding: UTF-8 -*- 
import sys,time 

Edición: Más información se puede encontrar in excellent the Dive into Python book

+2

setdefaultencoding() es nolonger en sys (a partir de v2.0 de acuerdo con los documentos del módulo). –

+0

hmmmm, extraño ... lo investigaré. –

+0

No puedo probarlo ahora, pero sé que he usado este truco en una versión posterior - 2.5 en Windows. –

9

El código de abajo hará que la salida a la consola de Python como UTF-8, incluso en Windows.

La consola mostrará 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á un resultado consistente de su secuencia de comandos en todas las plataformas. Podrá redirigir la salida a un archivo.

A continuación se probó el código 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" 
+0

¿Hay alguna manera de evitar esto usando solo una consola diferente? – endolith

+6

['cp65001! = Utf-8'] (http://bugs.python.org/msg97731) – jfs

+0

@sorin: ¿Por qué primero 'importas win32console' fuera de' try 'y luego lo haces condicionalmente dentro de un' intentar'? No es ese tipo de inútil (la primera 'importación') – 0xC0000022L

22

A pesar de las otras respuestas que suenan plausibles que sugieren el cambio de la página de códigos a 65001, que does not work. (Además, cambiar la codificación predeterminada usando sys.setdefaultencoding es not a good idea.)

Consulte this question para obtener detalles y código que sí funciona.

+2

'win-unicode-console' El paquete Python (basado en su código) le permite evitar modificar su script si imprime Unicode directamente usando el comando [' py -mrun your_script.py'] (http://stackoverflow.com/a/ 32176732/4279). – jfs

11

Si no está interesado en obtener una representación fiable del mal carácter (s) se usa algo como esto (el trabajo 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 caracteres incorrectos de la cadena se convertirán en una representación que la consola de Windows imprimirá.

+0

'.encode ('utf8'). Decode (sys.stdout.encoding)' conduce a mojibake, por ejemplo, 'u" \ N {EM DASH} ". Encode ('utf-8'). Decode ('cp437') '->' ΓÇö' – jfs

+0

Simplemente 'print (s.encode ('utf-8'))' puede ser una mejor forma de evitar los errores del compilador. En cambio, obtiene salida \ xNN para caracteres no imprimibles, que fue suficiente para mis mensajes de diagnóstico. –

+1

Esto es enorme, * espectacularmente * incorrecto. La codificación a UTF-8 y la decodificación como un juego de caracteres de 8 bits a) a menudo fallarán, no todas las páginas de códigos tienen caracteres para todos los valores de 256 bytes, yb) * siempre * la interpretación incorrecta de los datos, produciendo un [Mojibake] (https : //en.wikipedia.org/wiki/Mojibake) mess en su lugar. –

46

Actualización:Python 3.6 implementos PEP 528: Change Windows console encoding to UTF-8: la consola predeterminada en Windows ahora aceptar todos los caracteres Unicode. Internamente, usa la misma API Unicode como the win-unicode-console package mentioned below. print(unicode_string) debería funcionar ahora.


I get a UnicodeEncodeError: 'charmap' codec can't encode character... error.

El error significa que los caracteres Unicode que está intentando imprimir no se pueden representar mediante la corriente de codificación de caracteres (chcp) consola. La página de códigos es a menudo codificación de 8 bits como cp437 que puede representar sólo ~ 0x100 personajes de caracteres ~ 1 M 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

I assume this is because the Windows console does not accept Unicode-only characters. What's the best way around this?

consola de Windows sí acepta caracteres Unicode e incluso puede mostrarlos (sólo BMP) si la fuente correspondiente está configurada. WriteConsoleW() API se debe utilizar como se sugiere en @Daira Hopwood's answer. Se le puede llamar de forma transparente, es decir, que no es necesario y no debe modificar las secuencias de comandos si utiliza win-unicode-console package:

T:\> py -mpip install win-unicode-console 
T:\> py -mrun your_script.py 

Ver What's the deal with Python 3.4, Unicode, different languages and Windows?

Is there any way I can make Python automatically print a ? instead of failing in this situation?

Si es suficiente para reemplazar todos los caracteres con unencodable ? en su caso, entonces usted podría fijar PYTHONIOENCODING envvar:

T:\> set PYTHONIOENCODING=:replace 
T:\> python3 -c "print(u'[\N{EURO SIGN}]')" 
[?] 

en Python 3.6+, la codificación specif ied por PYTHONIOENCODING envvar se ignora para los búferes de la consola interactiva a menos que PYTHONLEGACYWINDOWSIOENCODING envvar se establezca en una cadena no vacía.

+0

"la consola predeterminada en Windows ahora aceptará todos los caracteres Unicode" ** PERO ** necesita configurar la consola: haga clic con el botón derecho en la parte superior de las ventanas (del cmd o el IDLE de python), por defecto/fuente elija la "Consola Lucida". (Los japoneses y los chinos no funcionan para mí, pero debería sobrevivir sin él ...) – JinSnow

+0

@Guillaume: la respuesta contiene la frase en ** negrita ** sobre la consola de Windows: * "si se configura la fuente correspondiente". * Esta respuesta no menciona IDLE pero no necesita configurar la fuente en ella (veo los caracteres japoneses y chinos perfectamente en IDLE de forma predeterminada. Pruebe 'print ('\ u4E01')', 'print ('\ u6b63 ') '). – jfs

+1

@Guillaume Incluso puede obtener chino si instala el paquete de idioma en Windows 10. Agregó fuentes de consola que admiten chino. –

0

Algo relacionado con la respuesta de J. F. Sebastian, pero más directo.

Si tiene este problema al imprimir en la consola/terminal, a continuación, hacer esto:

>set PYTHONIOENCODING=UTF-8 
+3

'set PYTHONIOENCODING = UTF-8' puede conducir a [mojibake] (http://goo.gl/QlkFXZ) si la consola usa una codificación diferente como cp437. ['cp65001' tiene varios problemas] (http://bugs.python.org/issue1602). Para imprimir Unicode en la consola de Windows, se debe utilizar la API Unicode ('WriteConsoleW()') como se sugiere en [mi respuesta] (http://stackoverflow.com/a/32176732/4279) donde 'PYTHONIOENCODING' se usa solo para reemplazar los caracteres que no se pueden representar en la página actual de códigos OEM con '?' ('WriteConsoleW()' funcionan incluso para dichos caracteres). 'PYTHONIOENCODING' se puede usar si la salida se redirige a un archivo. – jfs

2

Al igual que la respuesta de Giampaolo Rodolà, pero aún más sucia: Realmente, realmente 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 algo que significara que mi programa NO CRUZARía, y que entendí ... y también que no involucraba importar demasiados módulos exóticos (en particular, estoy usando Jython, por lo que la mitad de las veces un módulo de Python resulta no estar disponible lable).

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 de lo que escribir "imprimir" (y un poco más corto que el tipo de "safeprint") ...!

+0

Inteligente, una manera rápida y sucia de evitar el problema. Creo que esto es genial para una solución intermitente. – JFA

-1

preguntó James Sulak,

Is there any way I can make Python automatically print a ? instead of failing in this situation?

Otras soluciones recomiendan intentamos modificar el entorno Windows o reemplazar la función de Python print(). La respuesta a continuación se acerca más a cumplir con la solicitud de Sulak.

En Windows 7, Python 3.5 se pueden hacer para imprimir Unicode sin lanzar un UnicodeEncodeError de la siguiente manera:

    En lugar de:     print(text)
    sustituto:     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 punto noir

En lugar de

  n'était Halmalo más noir

Concedido punto qu'un, esta última es preferible ceteris paribus, pero por lo demás la primera es co completamente preciso para mensajes de diagnóstico. Debido a que muestra Unicode como valores literales de bytes, el primero también puede ayudar a diagnosticar problemas de codificación/decodificación.

Nota: Se necesita la llamada str() anterior porque de lo contrario encode() provoca Python para rechazar un carácter Unicode como una tupla de números.

1

Python 3.6 windows7: Hay varias formas de iniciar una python, puede usar la consola de python (que tiene un logotipo de python) o la consola de Windows (está escrito cmd.exe en ella).

No pude imprimir caracteres utf8 en la consola de Windows.Impresión de caracteres UTF-8 me tire 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 probar y no comprender la respuesta anterior descubrí que era sólo un problema de configuración. Haga clic derecho en la parte superior de las ventanas de la consola del cmd, en la pestaña font elija la consola lucida.

1

Para Python 2 intento:

print unicode(string, 'unicode-escape') 

Para Python 3 intento:

import os 
string = "002 Could've Would've Should've" 
os.system('echo ' + string) 

o tratar de ganar-Unicode-consola:

pip install win-unicode-console 
py -mrun your_script.py