UnicodeEncodeError: Der Codec 'latin-1' kann keine Zeichen codieren


91

Was kann diesen Fehler verursachen, wenn ich versuche, ein Fremdzeichen in die Datenbank einzufügen?

>>UnicodeEncodeError: 'latin-1' codec can't encode character u'\u201c' in position 0: ordinal not in range(256)

Und wie löse ich das?

Vielen Dank!


40
db = MySQLdb.connect (host = "localhost", user = "root", passwd = "", db = "testdb", use_unicode = True, charset = "utf8")
KyungHoon Kim

wow, @KyungHoonKim du hast mein Leben gerettet! Bis Sie gehen !
Florian Doyen

Antworten:


63

Das linke doppelte Anführungszeichen für das Zeichen U + 201C ist in der Latin-1-Codierung (ISO-8859-1) nicht vorhanden.

Es ist auf der Codepage 1252 (Westeuropa) enthalten. Dies ist eine Windows-spezifische Codierung, die auf ISO-8859-1 basiert, jedoch zusätzliche Zeichen in den Bereich 0x80-0x9F einfügt. Codepage 1252 wird häufig mit ISO-8859-1 verwechselt, und es ist ein ärgerliches, aber mittlerweile standardmäßiges Verhalten des Webbrowsers, dass der Browser Ihre Seiten stattdessen als cp1252 behandelt, wenn Sie sie als ISO-8859-1 bereitstellen. Es handelt sich jedoch tatsächlich um zwei unterschiedliche Codierungen:

>>> u'He said \u201CHello\u201D'.encode('iso-8859-1')
UnicodeEncodeError
>>> u'He said \u201CHello\u201D'.encode('cp1252')
'He said \x93Hello\x94'

Wenn Sie Ihre Datenbank nur als Byte-Speicher verwenden, können Sie cp1252 zum Codieren und anderer Zeichen verwenden, die auf der Windows Western-Codepage vorhanden sind. Wieder andere Unicode-Zeichen, die in cp1252 nicht vorhanden sind, verursachen Fehler.

Sie können encode(..., 'ignore')die Fehler unterdrücken, indem Sie die Zeichen entfernen. In diesem Jahrhundert sollten Sie jedoch UTF-8 sowohl in Ihrer Datenbank als auch auf Ihren Seiten verwenden. Diese Codierung ermöglicht die Verwendung eines beliebigen Zeichens. Idealerweise sollten Sie MySQL auch mitteilen, dass Sie UTF-8-Zeichenfolgen verwenden (indem Sie die Datenbankverbindung und die Sortierung für Zeichenfolgenspalten festlegen), damit der Vergleich und die Sortierung ohne Berücksichtigung der Groß- und Kleinschreibung richtig sind.


1
Ist nicht cp1252eine strikte Obermenge von ISO-8859-1? Wenn Browser eine ISO-8859-1-Seite erhalten, können sie diese so rendern, als wäre es CP1252, da 0x80-0x9Fohnehin keine Zeichen aus dem Bereich vorhanden sind .
MSalters

3
Nein, die Bytes 0x80–0x9F haben echte Zuweisungen in ISO-8859-1, die durch die Ergänzungen von cp1252 überschrieben werden, sodass es sich nicht um eine Obermenge handelt. Sie werden genau den Unicode-Zeichen U + 0080 - U + 009F zugeordnet, bei denen es sich um eine Auswahl von Steuerzeichen handelt. Es handelt sich um Steuerzeichen, die nicht sehr häufig verwendet werden, weshalb Browser damit davongekommen sind. Es ist jedoch ärgerlich, wenn Sie versuchen, eine Folge von Bytes als Unicode zu konvertieren.
Bobince

Das einzige Mal, dass ich jemals Zeichen im Bereich U + 0080-U + 009F in einer als ISO-8859-1 oder UTF-8 codierten Datei gesehen habe, war darauf zurückzuführen, dass ein Clown eine Reihe von Dateien verkettete, von denen einige in cp850 codiert waren und dann das resultierende Durcheinander von "latin1" nach UTF-8 zu transkodieren. Der Entwurf der HTML5-Spezifikation erwägt, dieses sehr praktische Browserverhalten (und eine ganze Reihe ähnlicher Fälle) zu heiligen
John Machin,

94

Ich bin auf dasselbe Problem gestoßen, als ich das Python MySQLdb-Modul verwendet habe. Da Sie mit MySQL nahezu alle gewünschten Binärdaten unabhängig vom Zeichensatz in einem Textfeld speichern können, habe ich hier meine Lösung gefunden:

Verwenden von UTF8 mit Python MySQLdb

Bearbeiten: Zitat aus der obigen URL, um die Anfrage im ersten Kommentar zu erfüllen ...

"UnicodeEncodeError: Der Codec 'latin-1' kann keine Zeichen codieren ..."

Dies liegt daran, dass MySQLdb normalerweise versucht, alles in Latin-1 zu codieren. Dies kann behoben werden, indem die folgenden Befehle direkt nach dem Herstellen der Verbindung ausgeführt werden:

db.set_character_set('utf8')
dbc.execute('SET NAMES utf8;')
dbc.execute('SET CHARACTER SET utf8;')
dbc.execute('SET character_set_connection=utf8;')

"db" ist das Ergebnis von MySQLdb.connect()und "dbc" ist das Ergebnis von db.cursor().


1
Es wird empfohlen, den relevanten Teil eines verknüpften Elements in der Antwort anzugeben. Der Link für zusätzliche Lektüre ist großartig, aber bitte versuchen Sie, sozusagen eine Zusammenfassung in Ihrer Antwort
einzufügen

@Fluffeh Und es war so.
CatShoes

1
Vielen Dank, hat wie ein Zauber funktioniert, nachdem ich 1000 andere Dinge ausprobiert habe.
Jürgen Riemer

2
Nur db.set_character_set ('utf8') sollte das Problem lösen
Pandurang Patil

21

Die beste Lösung ist

  1. Setzen Sie den Zeichensatz von mysql auf 'utf-8'.
  2. mag diesen Kommentar (hinzufügen use_unicode=Trueund charset="utf8")

    db = MySQLdb.connect (host = "localhost", user = "root", passwd = "", db = "testdb", use_unicode = True, charset = "utf8") - KyungHoon Kim 13. März 14 um 17:04 Uhr

Detail siehe:

class Connection(_mysql.connection):

    """MySQL Database Connection Object"""

    default_cursor = cursors.Cursor

    def __init__(self, *args, **kwargs):
        """

        Create a connection to the database. It is strongly recommended
        that you only use keyword parameters. Consult the MySQL C API
        documentation for more information.

        host
          string, host to connect

        user
          string, user to connect as

        passwd
          string, password to use

        db
          string, database to use

        port
          integer, TCP/IP port to connect to

        unix_socket
          string, location of unix_socket to use

        conv
          conversion dictionary, see MySQLdb.converters

        connect_timeout
          number of seconds to wait before the connection attempt
          fails.

        compress
          if set, compression is enabled

        named_pipe
          if set, a named pipe is used to connect (Windows only)

        init_command
          command which is run once the connection is created

        read_default_file
          file from which default client values are read

        read_default_group
          configuration group to use from the default file

        cursorclass
          class object, used to create cursors (keyword only)

        use_unicode
          If True, text-like columns are returned as unicode objects
          using the connection's character set.  Otherwise, text-like
          columns are returned as strings.  columns are returned as
          normal strings. Unicode objects will always be encoded to
          the connection's character set regardless of this setting.

        charset
          If supplied, the connection character set will be changed
          to this character set (MySQL-4.1 and newer). This implies
          use_unicode=True.

        sql_mode
          If supplied, the session SQL mode will be changed to this
          setting (MySQL-4.1 and newer). For more details and legal
          values, see the MySQL documentation.

        client_flag
          integer, flags to use or 0
          (see MySQL docs or constants/CLIENTS.py)

        ssl
          dictionary or mapping, contains SSL connection parameters;
          see the MySQL documentation for more details
          (mysql_ssl_set()).  If this is set, and the client does not
          support SSL, NotSupportedError will be raised.

        local_infile
          integer, non-zero enables LOAD LOCAL INFILE; zero disables

        autocommit
          If False (default), autocommit is disabled.
          If True, autocommit is enabled.
          If None, autocommit isn't set and server default is used.

        There are a number of undocumented, non-standard methods. See the
        documentation for the MySQL C API for some hints on what they do.

        """

1
Diese Antwort braucht mehr Upvotes. Dies ist eine saubere Lösung, mit der die Anwendungsschicht von unnötigen Codierungskosten befreit wird.
Yeaske

Toll! Dies ist genau das, wonach ich gesucht habe
Geek

Außerdem sollten wir besser auf mysql setzen, utf8mb4wenn wir emoji.etc haben. Beziehen Sie sich auf den Unterschied zwischen utf8mb4- und utf8-Zeichensätzen in mysql
Cheney

19

Ich hoffe, Ihre Datenbank ist mindestens UTF-8. Dann müssen Sie ausführen, yourstring.encode('utf-8')bevor Sie versuchen, es in die Datenbank zu stellen.


3

Sie versuchen, einen Unicode-Codepunkt \u201cmit einer Codierung zu speichern ISO-8859-1 / Latin-1, die diesen Codepunkt nicht beschreiben kann. Möglicherweise müssen Sie die Datenbank ändern, um utf-8 zu verwenden, und die Zeichenfolgendaten mit einer geeigneten Codierung speichern, oder Sie möchten Ihre Eingaben vor dem Speichern des Inhalts bereinigen. dh mit etwas wie Sam Rubys ausgezeichnetem i18n-Leitfaden . Das spricht über die Probleme, windows-1252die verursachen können, und schlägt vor, wie es verarbeitet werden soll, sowie Links zu Beispielcode!


2

SQLAlchemy-Benutzer können einfach ihr Feld als angeben convert_unicode=True.

Beispiel: sqlalchemy.String(1000, convert_unicode=True)

SQLAlchemy akzeptiert einfach Unicode-Objekte und gibt sie zurück, wobei die Codierung selbst behandelt wird.

Docs


1

Latin-1 (auch bekannt als ISO 8859-1 ) ist ein Codierungsschema für einzelne Oktettzeichen, und Sie können \u201c( ) nicht in ein Byte einpassen.

Wollten Sie UTF-8-Codierung verwenden?


1
Latin-1 codiert bestimmte Unicode-Zeichen, nur nicht dieses. Es spielt keine Rolle, ob \ u201c nicht in ein Byte passt. Windows-1252 ist ebenfalls ein Einzeloktett- Codierungsschema und enthält \ u201c.
Mark Tolonen

cp1253 (auch bekannt als windows-1253) ist ebenfalls ein Codierungsschema für einzelne Oktettzeichen und \u0391passt dennoch gut in ein Byte (insbesondere Byte 193). Sie können einen Blick auf nehmen möchten , dass ; Leute haben es hilfreich gefunden.
Zot

Unicode enthält Latin-1 / cp1253-Glyphen als 16-Bit-Codepunkte. Ich bin überrascht, dass die Kommentare das Gegenteil zu behaupten scheinen.
msw

1

Verwenden Sie das folgende Snippet, um den Text von Latein nach Englisch zu konvertieren

import unicodedata
def strip_accents(text):
    return "".join(char for char in
                   unicodedata.normalize('NFKD', text)
                   if unicodedata.category(char) != 'Mn')

strip_accents('áéíñóúü')

Ausgabe:

'aeinouu'


-3

Python: Sie müssen # - * - Kodierung: UTF-8 - * - (entfernen Sie die Leerzeichen um *) in die erste Zeile der Python-Datei einfügen. und fügen Sie dann dem zu codierenden Text Folgendes hinzu: .encode ('ascii', 'xmlcharrefreplace') . Dadurch werden alle Unicode-Zeichen durch das ASCII-Äquivalent ersetzt.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.