De foutmelding
UnicodeEncodeError: 'latin-1' codec can't encode character u'\u2026'
in position 35: ordinal not in range(256)
lijkt erop te wijzen dat een of andere Python-taalcode probeert het teken \u2026
. te converteren in een Latin-1 (ISO8859-1) string, en het faalt. Niet verrassend, dat karakter is U+2026 HORIZONTAL ELLIPSIS
, dat geen enkel equivalent teken heeft in ISO8859-1.
Je hebt het probleem opgelost door de zoekopdracht ?charset=utf8
. toe te voegen in uw SQLAlchemy-verbindingsaanroep:
import sqlalchemy
from sqlalchemy import create_engine, MetaData, Table
db = create_engine('mysql://user:[email protected]/db?charset=utf8')
De sectie Database-urls
van de SQLAlchemy-documentatie vertelt ons dat een URL die begint met mysql
geeft een MySQL-dialect aan, met behulp van de mysql-python
chauffeur.
De volgende sectie, Aangepaste DBAPI connect() argumenten , vertelt ons dat queryargumenten worden doorgegeven aan de onderliggende DBAPI.
Dus, wat doet de mysql-python
driver maken van een parameter {charset: 'utf8'}
? Sectie Functies en attributen
van hun documentatie zegt over de charset
attribuut "...Indien aanwezig, wordt de tekenset voor de verbinding gewijzigd in deze tekenset, als ze niet gelijk zijn."
Om erachter te komen wat de tekenset voor verbindingen betekent, gaan we naar 10.1.4. Verbindingstekensets en -sorteringen van de MySQL 5.6-referentiehandleiding. Om een lang verhaal kort te maken:MySQL kan inkomende query's interpreteren als een andere codering dan de tekenset van de database en anders dan de codering van de geretourneerde queryresultaten.
Aangezien het foutbericht dat je hebt gerapporteerd eruitziet als een Python-foutbericht in plaats van een SQL-foutbericht, vermoed ik dat iets in SQLAlchemy of mysql-python de query probeert te converteren naar een standaard verbindingscodering van latin-1
voordat u het verzendt. Dit is wat de fout veroorzaakt. Echter, de zoekreeks ?charset=utf8
in uw connect()
oproep verandert de verbindingscodering en de U+2026 HORIZONTAL ELLIPSIS
kan doorkomen.
Bijwerken: je vraagt ook:"Als ik de tekenset-optie verwijder en vervolgens de beschrijving codeer met .encode('cp1252'), gaat het prima. Hoe kan een weglatingsteken doorkomen met cp1252 maar niet met unicode?"
De codering cp1252
heeft
een horizontaal weglatingsteken bij bytewaarde \x85
. Het is dus mogelijk om een Unicode-string te coderen die U+2026 HORIZONTAL ELLIPSIS
bevat in cp1252 zonder fouten.
Onthoud ook dat in Python Unicode-tekenreeksen en bytetekenreeksen twee verschillende gegevenstypen zijn. Het is redelijk om te speculeren dat MySQLdb een beleid heeft om alleen bytestrings via een SQL-verbinding te verzenden. Het zou dus een vraag die als een Unicode-tekenreeks is ontvangen, coderen in een bytetekenreeks, maar een vraag die als een bytetekenreeks wordt ontvangen, alleen laten. (Dit is speculatie, ik heb de broncode niet bekeken.)
In de traceback die je hebt gepost, tonen de laatste twee regels (het dichtst bij waar de fout zich voordoet) de methodenamen literal
, gevolgd door unicode_literal
. Dat ondersteunt de theorie dat MySQLdb de query die het ontvangt als een Unicode-tekenreeks codeert in een bytetekenreeks.
Wanneer u de querystring zelf codeert, omzeilt u het deel van MySQLdb dat deze codering anders doet. Houd er echter rekening mee dat als u de queryreeks anders codeert dan de MySQL-verbindingstekenset vereist, u een coderingsfout krijgt en dat uw tekst waarschijnlijk verkeerd wordt opgeslagen.