Pergunta

Quando tento imprimir uma string Unicode em um console do Windows, recebo uma mensagem UnicodeEncodeError: 'charmap' codec can't encode character .... erro.Presumo que isso ocorra porque o console do Windows não aceita caracteres somente Unicode.Qual é a melhor maneira de contornar isso?Existe alguma maneira de fazer o Python imprimir automaticamente um ? em vez de falhar nesta situação?

Editar: Estou usando Python 2.5.


Observação: A resposta do @LasseV.Karlsen com a marca de seleção está meio desatualizada (de 2008).Por favor, use as soluções/respostas/sugestões abaixo com cuidado!!

Resposta @JFSebastian é mais relevante a partir de hoje (6 de janeiro de 2016).

Foi útil?

Solução

Observação: Esta resposta está meio desatualizada (de 2008).Por favor, use a solução abaixo com cuidado!!


Aqui está uma página que detalha o problema e uma solução (procure na página o texto Envolvendo sys.stdout em uma instância):

PrintFails-Python Wiki

Aqui está um trecho de código dessa 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
  Б
  Б

Há mais algumas informações nessa página, vale a pena ler.

Outras dicas

Atualizar: Pitão 3.6 implementos PEP 528:Altere a codificação do console do Windows para UTF-8: o console padrão do Windows agora aceitará todos os caracteres Unicode. Internamente, ele usa a mesma API Unicode que o win-unicode-console pacote mencionado abaixo. print(unicode_string) deve funcionar agora.


Eu recebo um UnicodeEncodeError: 'charmap' codec can't encode character... erro.

O erro significa que os caracteres Unicode que você está tentando imprimir não podem ser representados usando o atual (chcp) codificação de caracteres do console.A página de código geralmente é uma codificação de 8 bits, como cp437 que pode representar apenas aproximadamente 0x100 caracteres de aproximadamente 1 milhão de 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 

Presumo que isso ocorra porque o console do Windows não aceita caracteres somente Unicode.Qual é a melhor maneira de contornar isso?

O console do Windows aceita caracteres Unicode e pode até exibi-los (somente BMP) se a fonte correspondente estiver configurada. WriteConsoleW() A API deve ser usada conforme sugerido em Resposta de @Daira Hopwood.Ele pode ser chamado de forma transparente, ou seja, você não precisa e não deve modificar seus scripts se usar win-unicode-console pacote:

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

Ver Qual é o problema com Python 3.4, Unicode, diferentes linguagens e Windows?

Existe alguma maneira de fazer Python imprimir automaticamente um ? em vez de falhar nesta situação?

Se for suficiente substituir todos os caracteres não codificáveis ​​por ? no seu caso, então você pode definir PYTHONIOENCODING envvar:

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

No Python 3.6+, a codificação especificada por PYTHONIOENCODING envvar é ignorado para buffers de console interativos, a menos que PYTHONLEGACYWINDOWSIOENCODING envvar é definido como uma string não vazia.

Apesar das outras respostas aparentemente plausíveis que sugerem alterar a página de código para 65001, isso não funciona.(Além disso, alterar a codificação padrão usando sys.setdefaultencoding é não é uma boa ideia.)

Ver essa questão para obter detalhes e código que funciona.

Se você não estiver interessado em obter uma representação confiável dos caracteres ruins, você pode usar algo assim (trabalhando com python >= 2.6, incluindo 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}")

Os caracteres inválidos na string serão convertidos em uma representação que pode ser impressa pelo console do Windows.

O código abaixo fará com que a saída do Python seja console como UTF-8, mesmo no Windows.

O console exibirá bem os caracteres no Windows 7, mas no Windows XP não os exibirá bem, mas pelo menos funcionará e o mais importante, você terá uma saída consistente do seu script em todas as plataformas.Você poderá redirecionar a saída para um arquivo.

O código abaixo foi testado com Python 2.6 no 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 a resposta de Giampaolo Rodolà, mas ainda mais suja:Eu realmente pretendo passar muito tempo (em breve) entendendo todo o assunto das codificações e como elas se aplicam aos consoles Windoze,

No momento eu só queria algo que significasse que meu programa NÃO iria travar, e que eu entendi ...e também que não envolveu a importação de muitos módulos exóticos (em particular, estou usando Jython, então na metade das vezes um módulo Python não está disponível).

def pr(s):
    try:
        print(s)
    except UnicodeEncodeError:
        for c in s:
            try:
                print( c, end='')
            except UnicodeEncodeError:
                print( '?', end='')

NB "pr" é mais curto para digitar do que "print" (e um pouco mais curto para digitar do que "safeprint")...!

Basta inserir este código na linha de comando antes de executar o script python:

chcp 65001 & set PYTHONIOENCODING=utf-8

Para Python 2, tente:

print unicode(string, 'unicode-escape')

Para Python 3, tente:

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

Ou tente win-unicode-console:

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

A causa do seu problema é NÃO o console do Win não está disposto a aceitar Unicode (pois faz isso, pois acho que o Win2k é o padrão).É a codificação padrão do sistema.Experimente este código e veja o que ele oferece:

import sys
sys.getdefaultencoding()

Se diz ASCII, há sua causa ;-) Você precisa criar um arquivo chamado sitecustomize.py e colocá-lo no caminho do Python (eu o coloquei em /usr/lib/python2.5/site-packages, mas isso é diferente em Win - é c: python lib sites packages ou algo assim), com o seguinte conteúdo:

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

e talvez você também queira especificar a codificação em seus arquivos:

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

Editar:mais informações podem ser encontradas em excelente o livro Dive into Python

DR:

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

Eu mesmo me deparei com isso, trabalhando em um bot de chat do Twitch (IRC).(Python 2.7 mais recente)

Eu queria analisar mensagens de bate-papo para responder...

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

mas também imprima-os com segurança no console em um formato legível:

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

Isso corrigiu o problema do lançamento do bot UnicodeEncodeError: 'charmap' erros e substituiu os caracteres Unicode por ?.

Meio relacionado na resposta de J.F.Sebastian, mas mais direto.

Se você estiver tendo esse problema ao imprimir no console/terminal, faça o seguinte:

>set PYTHONIOENCODING=UTF-8

Python 3.6 windows7:Existem várias maneiras de iniciar um python: você pode usar o console python (que tem um logotipo python) ou o console do Windows (está escrito cmd.exe nele).

Não consegui imprimir caracteres utf8 no console do Windows.Imprimir caracteres utf-8 gera este erro:

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 

Depois de tentar e não entender a resposta acima, descobri que era apenas um problema de configuração.Clique com o botão direito na parte superior das janelas do console cmd, na guia font escolheu console lúcida.

James Sulak perguntou:

Existe alguma maneira de fazer o Python imprimir automaticamente um arquivo ?em vez de falhar nesta situação?

Outras soluções recomendam que tentemos modificar o ambiente Windows ou substituir o ambiente do Python print() função.A resposta abaixo chega mais perto de atender ao pedido de Sulak.

No Windows 7, o Python 3.5 pode ser feito para imprimir Unicode sem lançar um UnicodeEncodeError do seguinte modo:

No lugar de:print(text)
substituto: print(str(text).encode('utf-8'))

Em vez de lançar uma exceção, o Python agora exibe caracteres Unicode não imprimíveis como \xNN códigos hexadecimais, por exemplo:

  Halmalo n\xe2\x80\x99\xc3\xa9tait mais qu\xe2\x80\x99un ponto preto

Em vez de

  Halmalo n'était plus qu'un point noir

É verdade que o último é preferível ceteris paribus, mas por outro lado o primeiro é completamente preciso para mensagens de diagnóstico.Como exibe Unicode como valores de bytes literais, o primeiro também pode ajudar no diagnóstico de problemas de codificação/decodificação.

Observação: O str() a chamada acima é necessária porque caso contrário encode() faz com que o Python rejeite um caractere Unicode como uma tupla de números.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top