Pregunta

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

Editar: Estoy usando Python 2.5.


Nota: La respuesta de @ LasseV.Karlsen con la marca de verificación está algo desactualizada (de 2008).¡Utilice las soluciones/respuestas/sugerencias a continuación con cuidado!

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

¿Fue útil?

Solución

Nota: Esta respuesta está algo desactualizada (de 2008).¡Utilice la siguiente solución con cuidado!


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

Errores de impresión - Python Wiki

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, que vale la pena leer.

Otros consejos

Actualizar: Pitón 3.6 implementos PEP 528:Cambie 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 win-unicode-console paquete mencionado a continuación. print(unicode_string) debería funcionar ahora.


Yo tengo un UnicodeEncodeError: 'charmap' codec can't encode character... error.

El error significa que los caracteres Unicode que está intentando imprimir no se pueden representar usando el formato actual (chcp) codificación de caracteres de la consola.La página de códigos suele tener una 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 

Supongo que esto se debe a que la consola de Windows no acepta caracteres exclusivos de 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() La API debe usarse como se sugiere en La respuesta de @Daira Hopwood.Se puede llamar de forma transparente, es decir, no necesita ni debe modificar sus scripts si usa 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 forma de hacer que Python imprima automáticamente un ? en lugar de fracasar en esta situación?

Si es suficiente reemplazar todos los caracteres no codificables con ? en tu caso entonces podrías configurar 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 la consola interactiva a menos que PYTHONLEGACYWINDOWSIOENCODING envvar se establece en una cadena no vacía.

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 Buena idea.)

Ver esta pregunta para obtener detalles y código que funciona.

Si no está interesado en obtener una representación confiable de los personajes malos, puede usar algo como esto (trabajando con Python >= 2.6, incluido 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}")

Los caracteres incorrectos de la cadena se convertirán en una representación que la consola de Windows puede imprimir.

El siguiente código hará que la salida de Python a la consola sea 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, tendrá un resultado consistente de su script en todas las plataformas.Podrás redirigir la salida a un archivo.

El siguiente código se probó 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"

Como la respuesta de Giampaolo Rodolà, pero aún más sucia:Realmente tengo la intención de dedicar mucho tiempo (pronto) a comprender 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 FALLARÍA, y lo cual entendí...y tampoco implicó 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).

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 escribir que "print" (y bastante más corto de escribir que "safeprint")...!

Simplemente ingrese este código en la línea de comando antes de ejecutar el script en Python:

chcp 65001 & set PYTHONIOENCODING=utf-8

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

La causa de tu problema es NO la consola Win no está dispuesta a aceptar Unicode (ya que lo hace, supongo que Win2k de forma predeterminada).Es la codificación predeterminada del sistema.Pruebe este código y vea lo que le ofrece:

import sys
sys.getdefaultencoding()

Si dice ASCII, está su causa ;-) Debe crear un archivo llamado siteCustomize.py y ponerlo en la ruta de Python (lo pongo debajo /usr/lib/python2.5/site-packages, pero eso está diferente en Win - Es C: Python lib Site -Packages o algo), con los siguientes contenidos:

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

y quizás también quieras especificar la codificación en tus archivos:

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

Editar:se puede encontrar más información en excelente el libro Dive into Python

TL;DR:

print(yourstring.encode('ascii','replace'));

Me encontré con esto yo mismo, trabajando en un bot de chat de Twitch (IRC).(Python 2.7 más reciente)

Quería analizar los mensajes de chat para poder responder...

msg = s.recv(1024).decode("utf-8")

pero también imprímelos de forma segura en la consola en un formato legible por humanos:

print(msg.encode('ascii','replace'));

Esto corrigió el problema del lanzamiento del bot. UnicodeEncodeError: 'charmap' errores y reemplazó los caracteres Unicode con ?.

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

Si tiene este problema al imprimir en la consola/terminal, haga esto:

>set PYTHONIOENCODING=UTF-8

Python 3.6 ventanas 7:Hay varias formas de iniciar Python: puede usar la consola de Python (que tiene un logotipo de Python) o la consola de Windows (está escrito cmd.exe).

No pude imprimir caracteres utf8 en la consola de Windows.Al 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 entender la respuesta anterior y no poder entenderla, descubrí que era sólo un problema de configuración.Haga clic derecho en la parte superior de las ventanas de la consola cmd, en la pestaña font Elegí la consola Lucida.

James Sulak preguntó:

¿Hay alguna manera de hacer que Python imprima automáticamente un archivo?en lugar de fracasar en esta situación?

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

En Windows 7, se puede hacer que Python 3.5 imprima Unicode sin generar un UnicodeEncodeError como sigue:

En lugar de:print(text)
sustituto: print(str(text).encode('utf-8'))

En lugar de generar 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 negro

En lugar de

  Halmalo n'était plus qu'un point noir

Por supuesto, esto último es preferible. ceteris paribus, pero por lo demás, el primero es completamente preciso para los mensajes de diagnóstico.Debido a que muestra Unicode como valores de bytes literales, el primero también puede ayudar a diagnosticar problemas de codificación/decodificación.

Nota: El str() La llamada anterior es necesaria porque de lo contrario encode() hace que Python rechace un carácter Unicode como una tupla de números.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top