UnicodeEncodeError: codec 'latin-1' tidak dapat menyandikan karakter

96

Apa yang menyebabkan kesalahan ini ketika saya mencoba memasukkan karakter asing ke dalam database?

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

Dan bagaimana cara mengatasinya?

Terima kasih!

menjerat
sumber
40
db = MySQLdb.connect (host = "localhost", user = "root", passwd = "", db = "testdb", use_unicode = True, charset = "utf8")
KyungHoon Kim
wow, @KyungoonKim kamu menyelamatkan hidupku! Pergilah!
Florian Doyen

Jawaban:

66

Karakter U + 201C Tanda Kutip Ganda Kiri tidak ada dalam pengkodean Latin-1 (ISO-8859-1).

Hal ini hadir dalam halaman kode 1252 (Eropa Barat). Ini adalah pengkodean khusus Windows yang didasarkan pada ISO-8859-1 tetapi menempatkan karakter tambahan ke dalam kisaran 0x80-0x9F. Halaman kode 1252 sering disalahartikan dengan ISO-8859-1, dan ini adalah perilaku browser web standar yang menjengkelkan bahwa jika Anda menyajikan halaman Anda sebagai ISO-8859-1, browser akan memperlakukannya sebagai cp1252. Namun, keduanya sebenarnya adalah dua pengkodean yang berbeda:

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

Jika Anda menggunakan database Anda hanya sebagai penyimpanan byte, Anda dapat menggunakan cp1252 untuk menyandikan dan karakter lain yang ada di halaman kode Windows Western. Tetapi karakter Unicode lain yang tidak ada di cp1252 akan menyebabkan kesalahan.

Anda dapat menggunakan encode(..., 'ignore')untuk menekan kesalahan dengan menghilangkan karakter, tetapi sebenarnya di abad ini Anda harus menggunakan UTF-8 di database dan halaman Anda. Pengkodean ini memungkinkan karakter apa pun untuk digunakan. Idealnya Anda juga harus memberi tahu MySQL bahwa Anda menggunakan string UTF-8 (dengan mengatur koneksi database dan pemeriksaan pada kolom string), sehingga dapat memperoleh perbandingan dan pengurutan yang tidak peka huruf besar / kecil.

bobince
sumber
1
Bukankah cp1252superset ketat dari ISO-8859-1? Yaitu ketika browser menerima halaman ISO-8859-1, mereka dapat membuatnya seolah-olah CP1252 karena tidak akan ada karakter apa pun dari rentang 0x80-0x9Ftersebut.
MSalters
3
Tidak, byte 0x80–0x9F memang memiliki tugas nyata dalam ISO-8859-1, yang diganti dengan tambahan cp1252 jadi ini bukan superset. Mereka memetakan secara tepat ke karakter Unicode U + 0080 – U + 009F, yang merupakan pilihan karakter kontrol. Mereka mengontrol karakter yang tidak terlalu banyak digunakan, itulah sebabnya browser lolos begitu saja, tetapi menjengkelkan ketika Anda mencoba untuk mengubah urutan byte-as-Unicode.
bobince
Satu-satunya saat saya pernah melihat karakter dalam kisaran U + 0080-U + 009F dalam file yang dikodekan sebagai ISO-8859-1 atau UTF-8 dihasilkan dari beberapa badut yang menggabungkan banyak file yang beberapa di antaranya dikodekan dalam cp850 dan kemudian transcoding kekacauan yang dihasilkan dari "latin1" ke UTF-8. Draf spesifikasi HTML5 sedang mempertimbangkan untuk menguduskan perilaku peramban yang sangat praktis itu (dan banyak kasus serupa) - lihat whatwg.org/specs/web-apps/current-work/multipage/…
John Machin
94

Saya mengalami masalah yang sama ini saat menggunakan modul Python MySQLdb. Karena MySQL akan membiarkan Anda menyimpan hampir semua data biner yang Anda inginkan dalam bidang teks terlepas dari kumpulan karakternya, saya menemukan solusi saya di sini:

Menggunakan UTF8 dengan Python MySQLdb

Edit: Kutipan dari URL di atas untuk memenuhi permintaan di komentar pertama ...

"UnicodeEncodeError: codec 'latin-1' tidak dapat menyandikan karakter ..."

Ini karena MySQLdb biasanya mencoba menyandikan semuanya ke latin-1. Ini dapat diperbaiki dengan menjalankan perintah berikut tepat setelah Anda membuat koneksi:

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

"db" adalah hasil dari MySQLdb.connect(), dan "dbc" adalah hasil dari db.cursor().

Nick
sumber
1
Disarankan agar bagian yang relevan dari item terkait disediakan dalam jawaban. Tautan untuk bacaan tambahan bagus, tapi tolong coba masukkan ringkasan eksekutif dalam jawaban Anda jadi untuk berbicara :)
Fluffeh
@Flueheh Dan memang begitu.
CatShoes
1
terima kasih besar, bekerja seperti pesona setelah mencoba 1000 hal lainnya.
Juergen Riemer
2
Hanya db.set_character_set ('utf8') yang seharusnya menyelesaikan masalah
Pandurang Patil
21

Solusi terbaiknya adalah

  1. setel charset mysql ke 'utf-8'
  2. lakukan seperti komentar ini (tambah use_unicode=Truedan charset="utf8")

    db = MySQLdb.connect (host = "localhost", user = "root", passwd = "", db = "testdb", use_unicode = True, charset = "utf8") - KyungHoon Kim 13 Maret '14 pukul 17:04

detail lihat:

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.

        """
Cheney
sumber
1
Jawaban ini membutuhkan lebih banyak suara positif. Ini adalah solusi yang bersih, membersihkan lapisan aplikasi dari biaya pengkodean yang tidak perlu.
yeaske
Bagus! Ini persis seperti yang saya cari
Geek
Selain itu, sebaiknya kita mengatur utf8mb4untuk mysql jika memiliki emoji.etc, lihat apa-perbedaan-antara-utf8mb4-dan-utf8-charsets-in-mysql
Cheney
20

Saya harap database Anda minimal UTF-8. Kemudian Anda harus menjalankannya yourstring.encode('utf-8')sebelum mencoba memasukkannya ke dalam database.

knitti
sumber
3

Anda mencoba untuk menyimpan titik \u201ckode Unicode menggunakan pengkodean ISO-8859-1 / Latin-1yang tidak dapat menggambarkan titik kode itu. Anda mungkin perlu mengubah database untuk menggunakan utf-8, dan menyimpan data string menggunakan pengkodean yang sesuai, atau Anda mungkin ingin membersihkan masukan Anda sebelum menyimpan konten; yaitu menggunakan sesuatu seperti panduan i18n Sam Ruby yang sangat baik . Itu berbicara tentang masalah yang windows-1252dapat menyebabkan, dan menyarankan cara memprosesnya, ditambah tautan ke kode sampel!

jabley
sumber
2

Pengguna SQLAlchemy cukup menentukan kolom mereka sebagai convert_unicode=True.

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

SQLAlchemy hanya akan menerima objek unicode dan mengembalikannya, menangani penyandian itu sendiri.

Docs

mgojohn
sumber
2

Gunakan potongan di bawah ini untuk mengubah teks dari bahasa Latin ke bahasa Inggris

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

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

keluaran:

'aeinouu'

Uday Allu
sumber
1

Latin-1 (alias ISO 8859-1 ) adalah skema pengkodean karakter oktet tunggal, dan Anda tidak dapat memasukkan \u201c( ) ke dalam byte.

Apakah Anda bermaksud menggunakan encoding UTF-8?

msw
sumber
1
Latin-1 mengkodekan karakter Unicode tertentu , hanya saja bukan yang itu. Tidak masalah jika \ u201c tidak muat dalam satu byte. windows-1252 adalah skema oktet pengkodean tunggal juga, dan tidak termasuk \ u201c.
Mark Tolonen
cp1253 (alias windows-1253) juga merupakan skema pengkodean karakter oktet tunggal, namun \u0391cocok dengan baik dalam satu byte (khususnya, 193 byte). Anda mungkin ingin melihat itu ; orang merasa terbantu.
tzot
Unicode menggabungkan mesin terbang Latin-1 / cp1253 sebagai titik kode 16-bit. Saya terkejut bahwa komentar-komentar itu tampaknya mengklaim sebaliknya.
msw
-3

Python: Anda perlu menambahkan # - * - coding: UTF-8 - * - (menghapus spasi di sekitar *) ke baris pertama file python. dan kemudian tambahkan berikut ini ke teks untuk menyandikan: .encode ('ascii', 'xmlcharrefreplace') . Ini akan mengganti semua karakter unicode dengan yang setara dengan ASCII-nya.

nids
sumber