sql >> Databáze >  >> RDS >> Mysql

Jak přiměju SQLAlchemy, aby správně vložila unicode elipsu do tabulky mySQL?

Chybová zpráva

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

Zdá se, že to naznačuje, že se nějaký kód jazyka Python pokouší převést znak \u2026 do řetězce Latin-1 (ISO8859-1) a selhává. Není divu, že tato postava je U+2026 HORIZONTAL ELLIPSIS , který nemá v ISO8859-1 jediný ekvivalentní znak.

Problém jste vyřešili přidáním dotazu ?charset=utf8 ve volání připojení SQLAlchemy:

import sqlalchemy
from sqlalchemy import create_engine, MetaData, Table

db = create_engine('mysql://user:[email protected]/db?charset=utf8')

Sekce Adresy URL databáze dokumentace SQLAlchemy nám říká, že URL začínající mysql označuje dialekt MySQL pomocí mysql-python řidič.

Následující část, Vlastní DBAPI argumenty connect() , nám říká, že argumenty dotazu jsou předány základnímu DBAPI.

Co tedy znamená mysql-python ovladač vytvoří parametr {charset: 'utf8'} ? Sekce Funkce a atributy jejich dokumentace říká o charset atribut "...Pokud existuje, znaková sada připojení bude změněna na tuto znakovou sadu, pokud nejsou stejné."

Chcete-li zjistit, co znamená znaková sada připojení, obraťte se na 10.1.4. Připojení znakové sady a řazení referenční příručky MySQL 5.6. Abych to zkrátil, MySQL může interpretovat příchozí dotazy jako kódování odlišné od znakové sady databáze a odlišné od kódování vrácených výsledků dotazu.

Protože chybová zpráva, kterou jste nahlásili, vypadá spíše jako Python než jako chybová zpráva SQL, budu spekulovat, že se něco v SQLAlchemy nebo mysql-python pokouší převést dotaz na výchozí kódování připojení latin-1 před odesláním. To je to, co spouští chybu. Řetězec dotazu však ?charset=utf8 ve vašem connect() volání změní kódování připojení a U+2026 HORIZONTAL ELLIPSIS je schopen projít.

Aktualizace: také se ptáte:"Pokud odstraním možnost znakové sady a poté zakóduji popis pomocí .encode('cp1252'), projde to v pohodě. Jak je elipsa schopná projít s cp1252, ale ne unicode?"

kódování cp1252 znak vodorovné elipsy s hodnotou bajtu \x85 . Je tedy možné zakódovat řetězec Unicode obsahující U+2026 HORIZONTAL ELLIPSIS do cp1252 bez chyby.

Pamatujte také, že v Pythonu jsou řetězce Unicode a bajtové řetězce dva různé datové typy. Je rozumné spekulovat, že MySQLdb může mít politiku odesílání pouze bajtových řetězců přes SQL připojení. Dotaz přijatý jako řetězec Unicode by tedy zakódoval do bajtového řetězce, ale dotaz přijatý jako bajtový řetězec by ponechal sám. (Toto je spekulace, nedíval jsem se na zdrojový kód.)

Ve zpětném sledování, které jste zveřejnili, jsou na posledních dvou řádcích (nejblíže místu, kde došlo k chybě) uvedeny názvy metod literal , následovaný unicode_literal . To podporuje teorii, že MySQLdb kóduje dotaz, který obdrží, jako řetězec Unicode do bajtového řetězce.

Když sami kódujete řetězec dotazu, obcházíte část MySQLdb, která toto kódování provádí jinak. Všimněte si však, že pokud zakódujete řetězec dotazu jinak, než vyžaduje znaková sada připojení MySQL, budete mít nesoulad v kódování a váš text bude pravděpodobně uložen špatně.



  1. Funkce vs uložené procedury

  2. Zřetězit více řádků do jednotlivých řádků v MySQL

  3. Jak pivotovat schéma entity-atributu-hodnoty MySQL

  4. Vložení do databáze (mysql) pomocí Ajaxu a PHP