Python, Unicode, e o console do Windows

votos
104

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

Edit: eu estou usando o Python 2.5.


Nota: @ LasseV.Karlsen resposta com a marca de seleção é uma espécie de desatualizado (de 2008). Utilize as soluções / respostas / sugestões abaixo com cuidado !!

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

Publicado 07/08/2008 em 23:26
fonte usuário
Em outras línguas...                            


13 respostas

votos
50

Update: Python 3.6 implementa PEP 528: Console de codificação Mudança Windows para UTF-8 : o console padrão no Windows agora irá aceitar todos os caracteres Unicode. Internamente, ele usa a mesma API Unicode como o win-unicode-consolepacote mencionado abaixo . print(unicode_string)deverá 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 pode ser representado usando o atual ( chcp) caráter console de codificação. A página de código é frequentemente 8 bits de codificação, tais como cp437que podem representar apenas ~ 0x100 caracteres de caracteres ~ 1M Unicode:

>>> u "\ N {SINAL EURO}". Codificar ( 'CP437')
Traceback (chamada mais recente passada):
...
UnicodeEncodeError: codec 'charmap' não pode codificar caráter '\ u20AC' na posição 0:
caráter mapeia para 

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

Console do Windows não aceita caracteres Unicode e pode até mesmo exibi-los (somente BMP) se a fonte correspondente está configurado . WriteConsoleW()API deve ser usado como sugerido na 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 você usar o win-unicode-consolepacote :

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

Veja Qual é o negócio com o Python 3.4, Unicode, diferentes línguas e Windows?

Existe alguma maneira eu posso fazer Python imprimir automaticamente uma ?vez de falhar nesta situação?

Se é suficiente para substituir todos os caracteres unencodable com ?no seu caso, então você pode definir PYTHONIOENCODINGenvvar :

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

Em Python 3.6+, a codificação especificada por PYTHONIOENCODINGenwar é ignorado para buffers de consola interactiva, a menos que PYTHONLEGACYWINDOWSIOENCODINGenwar é definido como uma cadeia não-vazia.

Respondeu 24/08/2015 em 07:35
fonte usuário

votos
29

Nota: Esta resposta é uma espécie de desatualizado (de 2008). Utilize a solução abaixo com cuidado !!


Aqui está uma página que detalha o problema e uma solução (pesquisar a página para o texto sys.stdout de envolvimento em uma instância ):

PrintFails - Python Wiki

Aqui está um trecho de código a partir 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 sobre essa página, bem a pena uma leitura.

Respondeu 07/08/2008 em 23:32
fonte usuário

votos
22

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

Veja esta pergunta para obter detalhes e código que funciona.

Respondeu 09/01/2011 em 06:07
fonte usuário

votos
11

Se você não estiver interessado em obter uma representação fiel do mau caráter (s) que você pode usar algo como isto (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}")

O mau caráter (s) na cadeia será convertida em uma representação que pode ser impresso pelo console do Windows.

Respondeu 19/05/2012 em 19:48
fonte usuário

votos
9

O código abaixo fará saída Python para consolar como UTF-8, mesmo no Windows.

A consola apresenta os personagens bem no Windows 7, mas no Windows XP não vai exibi-los bem, mas pelo menos ele vai trabalhar e mais importante que você terá uma saída consistente de seu script em todas as plataformas. Você vai ser capaz de redirecionar a saída para um arquivo.

Abaixo código 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"
Respondeu 06/01/2010 em 14:38
fonte usuário

votos
3

Basta digitar esse código em linha de comando antes de executar script python:

chcp 65001 & set PYTHONIOENCODING=utf-8
Respondeu 02/10/2018 em 22:11
fonte usuário

votos
2

Para Python 2 try:

print unicode(string, 'unicode-escape')

Para Python 3 tentativa:

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

Ou tente ganhar-unicode-console:

pip install win-unicode-console
py -mrun your_script.py
Respondeu 24/08/2017 em 18:00
fonte usuário

votos
2

Como a resposta de Giampaolo Rodolà, mas ainda mais suja: Eu realmente, realmente a intenção de passar um longo tempo (em breve) compreender todo o assunto de codificações e como eles se aplicam a Windoze consoles,

No momento eu só queria sthg o que significaria o meu programa não iria falhar, e que eu entendi ... e também que não envolvem a importação de muitos módulos exóticas (em particular, eu estou usando Jython, então metade do tempo de um Python módulo acaba por não no fato de estar 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 de "print" (e um pouco mais curto para escrever do que "safeprint") ...!

Respondeu 09/03/2016 em 22:14
fonte usuário

votos
1

TL; DR:

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

Corri para isso mesmo, trabalhando em um bot Twitch Chat (IRC). (2,7 Python mais recente)

Eu queria analisar mensagens de chat para responder ...

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

mas também imprimi-los com segurança para o console em um formato legível:

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

Isso corrigiu o problema dos bot jogando UnicodeEncodeError: 'charmap'erros e substituídos os caracteres Unicode com ?.

Respondeu 01/07/2018 em 15:52
fonte usuário

votos
1

Python 3.6 windows7: Há várias formas para lançar um python você poderia usar o console python (que tem um logotipo python sobre ele) ou o console do Windows (é cmd.exe escrito nele).

Eu não conseguia imprimir caracteres utf8 no console do Windows. Impressão de caracteres UTF-8 deitar-me 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 compreender a resposta acima eu descobri que era apenas um problema de configuração. Botão direito do mouse na parte superior das janelas do console cmd, na guia fontescolheu Lucida Console.

Respondeu 11/05/2017 em 20:08
fonte usuário

votos
1

Kind of relacionada à resposta por JF Sebastian, mas mais direto.

Se você está tendo esse problema ao imprimir para o console / terminal, em seguida, faça o seguinte:

>set PYTHONIOENCODING=UTF-8
Respondeu 16/12/2015 em 07:53
fonte usuário

votos
1

A causa do seu problema é não o Win console não dispostos a aceitar Unicode (como ele faz isso desde que eu acho que Win2k por padrão). É a codificação padrão do sistema. Tente este código e ver o que ele dá-lhe:

import sys
sys.getdefaultencoding()

se ele diz ascii, não sua causa ;-) Você tem que criar um arquivo chamado sitecustomize.py e colocá-lo sob caminho python (eu colocá-lo sob /usr/lib/python2.5/site-packages, mas que é dife em Win - é c: \ python \ lib \ site-packages ou algo assim), com o seguinte conteúdo:

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

e, talvez, você pode querer especificar a codificação em seus arquivos, bem como:

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

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

Respondeu 11/08/2008 em 18:58
fonte usuário

votos
0

James Sulak perguntou:

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

Outras soluções recomendo que tente modificar o ambiente Windows ou substituir do Python print()função. A resposta abaixo vem mais perto de cumprir o pedido do Sulak.

No Windows 7, o Python 3.5 pode ser feita para imprimir Unicode sem jogar um UnicodeEncodeErrorda seguinte forma:

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

Em vez de lançar uma exceçã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 noir

Ao invés de

  Halmalo n'était mais noir ponto qu'un

Concedido, este último é preferível ceteris paribus , mas por outro lado o primeiro é completamente exata para mensagens de diagnóstico. Porque ele exibe Unicode como literal byte valoriza o primeiro pode também ajudar a diagnosticar problemas de codificação / descodificação.

Nota: A str()chamada acima é necessário porque caso contrário encode()provoca Python para rejeitar um caractere Unicode como uma tupla de números.

Respondeu 14/05/2016 em 17:47
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more