Domanda

Quando provo a stampare una stringa Unicode in una console Windows, ottengo un file UnicodeEncodeError: 'charmap' codec can't encode character .... errore.Presumo che ciò sia dovuto al fatto che la console Windows non accetta caratteri solo Unicode.Qual è il modo migliore per aggirare questo problema?Esiste un modo per fare in modo che Python stampi automaticamente a ? invece di fallire in questa situazione?

Modificare: Sto usando Python 2.5.


Nota: @ LasseV.Karlsen la risposta con il segno di spunta è un po' obsoleta (dal 2008).Si prega di utilizzare le soluzioni/risposte/suggerimenti di seguito con attenzione!!

@JFSebastian risposta è più rilevante ad oggi (6 gennaio 2016).

È stato utile?

Soluzione

Nota: Questa risposta è un po' obsoleta (dal 2008).Si prega di utilizzare la soluzione seguente con attenzione!!


Ecco una pagina che descrive in dettaglio il problema e una soluzione (cerca nella pagina il testo Avvolgimento di sys.stdout in un'istanza):

PrintFails - Wiki Python

Ecco un estratto del codice da quella pagina:

$ 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
  Б
  Б

Ci sono altre informazioni in quella pagina, vale la pena leggerle.

Altri suggerimenti

Aggiornamento: Pitone 3.6 implementa PEP528:Modifica la codifica della console Windows in UTF-8: la console predefinita su Windows ora accetterà tutti i caratteri Unicode. Internamente utilizza la stessa API Unicode di IL win-unicode-console pacchetto menzionato di seguito. print(unicode_string) dovrebbe funzionare solo adesso.


ottengo un UnicodeEncodeError: 'charmap' codec can't encode character... errore.

L'errore significa che i caratteri Unicode che stai tentando di stampare non possono essere rappresentati utilizzando l'attuale (chcp) codifica dei caratteri della console.La tabella codici è spesso una codifica a 8 bit come cp437 che può rappresentare solo ~0x100 caratteri da ~1M di caratteri 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 che ciò sia dovuto al fatto che la console Windows non accetta caratteri solo Unicode.Qual è il modo migliore per aggirare questo problema?

La console Windows accetta i caratteri Unicode e può persino visualizzarli (solo BMP) se è configurato il carattere corrispondente. WriteConsoleW() L'API deve essere utilizzata come suggerito in La risposta di @Daira Hopwood.Può essere chiamato in modo trasparente, ovvero non è necessario e non è necessario modificare gli script se si utilizza win-unicode-console pacchetto:

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

Vedere Qual è il problema con Python 3.4, Unicode, linguaggi diversi e Windows?

C'è un modo per far stampare automaticamente Python a ? invece di fallire in questa situazione?

Se è sufficiente sostituire tutti i caratteri non codificabili con ? nel tuo caso allora potresti impostare PYTHONIOENCODING envvar:

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

In Python 3.6+, la codifica specificata da PYTHONIOENCODING envvar viene ignorato per i buffer della console interattiva a meno che PYTHONLEGACYWINDOWSIOENCODING envvar è impostato su una stringa non vuota.

Nonostante le altre risposte apparentemente plausibili che suggeriscono di modificare la tabella codici in 65001, quella non funziona.(Inoltre, modificando la codifica predefinita utilizzando sys.setdefaultencoding È non è una buona idea.)

Vedere questa domanda per i dettagli e il codice che funziona.

Se non sei interessato a ottenere una rappresentazione affidabile dei personaggi cattivi potresti usare qualcosa di simile (lavorando con Python >= 2.6, incluso 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}")

I caratteri errati nella stringa verranno convertiti in una rappresentazione stampabile dalla console Windows.

Il codice seguente renderà l'output di Python sulla console come UTF-8 anche su Windows.

La console visualizzerà bene i caratteri su Windows 7 ma su Windows XP non li visualizzerà bene, ma almeno funzionerà e, cosa più importante, avrai un output coerente dal tuo script su tutte le piattaforme.Sarai in grado di reindirizzare l'output su un file.

Il codice seguente è stato testato con Python 2.6 su 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"

Come la risposta di Giampaolo Rodolà, ma ancora più sporca:Ho davvero, davvero intenzione di dedicare molto tempo (presto) alla comprensione dell'intero argomento delle codifiche e di come si applicano alle console Windoze,

Per il momento volevo solo qualcosa che significasse che il mio programma NON CRASHERA', e che ho capito...e anche che non comportava l'importazione di troppi moduli esotici (in particolare sto usando Jython, quindi la metà delle volte un modulo Python risulta non essere disponibile).

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

NB "pr" è più corto da scrivere di "print" (e un po' più corto da scrivere di "safeprint")...!

Basta inserire questo codice nella riga di comando prima di eseguire lo script Python:

chcp 65001 & set PYTHONIOENCODING=utf-8

Per Python 2 prova:

print unicode(string, 'unicode-escape')

Per Python 3 prova:

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

Oppure prova win-unicode-console:

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

La causa del tuo problema è NON la console Win non è disposta ad accettare Unicode (come fa poiché immagino Win2k per impostazione predefinita).È la codifica predefinita del sistema.Prova questo codice e guarda cosa ti dà:

import sys
sys.getdefaultencoding()

Se dice ASCII, c'è la tua causa ;-) Devi creare un file chiamato sitecustomize.py e metterlo sotto Python Path (l'ho messo sotto /usr/lib/python2.5/site-packages, ma questo è diverso Win - È C: Python lib Site -Packages o qualcosa del genere), con i seguenti contenuti:

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

e forse potresti voler specificare anche la codifica nei tuoi file:

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

Modificare:maggiori informazioni possono essere trovate in eccellente il libro Dive into Python

TL;DR:

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

Mi sono imbattuto in questo io stesso, lavorando su un bot di chat Twitch (IRC).(Python 2.7 più recente)

Volevo analizzare i messaggi di chat per rispondere...

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

ma stampali anche in modo sicuro sulla console in un formato leggibile dall'uomo:

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

Ciò ha corretto il problema del lancio del bot UnicodeEncodeError: 'charmap' errori e ho sostituito i caratteri Unicode con ?.

Un po' correlato alla risposta di J.F.Sebastian, ma più diretto.

Se riscontri questo problema durante la stampa sulla console/terminale, procedi come segue:

>set PYTHONIOENCODING=UTF-8

Python 3.6 Windows7:Esistono diversi modi per avviare Python: è possibile utilizzare la console Python (che ha un logo Python su di essa) o la console Windows (su di essa è scritto cmd.exe).

Non sono riuscito a stampare i caratteri utf8 nella console di Windows.La stampa dei caratteri utf-8 mi dà questo errore:

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 

Dopo aver provato e non riuscendo a comprendere la risposta sopra, ho scoperto che si trattava solo di un problema di impostazione.Fare clic con il tasto destro sulla parte superiore delle finestre della console cmd, sulla scheda font ha scelto la consolle lucida.

James Sulak ha chiesto:

Esiste un modo per fare in modo che Python stampi automaticamente un ?invece di fallire in questa situazione?

Altre soluzioni consigliano di tentare di modificare l'ambiente Windows o sostituire quello di Python print() funzione.La risposta che segue si avvicina di più alla richiesta di Sulak.

In Windows 7, è possibile fare in modo che Python 3.5 stampi Unicode senza generare a UnicodeEncodeError come segue:

Al posto di:print(text)
sostituire: print(str(text).encode('utf-8'))

Invece di lanciare un'eccezione, Python ora visualizza i caratteri Unicode non stampabili come \xNN codici esadecimali, ad esempio:

  Halmalo n\xe2\x80\x99\xc3\xa9tait plus qu\xe2\x80\x99un punto nero

Invece di

  Halmalo n'était plus qu'un point noir

Certo, quest'ultima è preferibile ceteris paribus, ma per il resto il primo è completamente accurato per i messaggi diagnostici.Poiché visualizza Unicode come valori byte letterali, il primo può anche aiutare nella diagnosi dei problemi di codifica/decodifica.

Nota: IL str() la chiamata sopra è necessaria perché altrimenti encode() fa sì che Python rifiuti un carattere Unicode come tupla di numeri.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top