sql >> Databasteknik >  >> RDS >> Mysql

Hur får jag SQLAlchemy att korrekt infoga en unicode-ellipsis i en mySQL-tabell?

Felmeddelandet

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

verkar indikera att någon Python-språkkod försöker konvertera tecknet \u2026 till en Latin-1 (ISO8859-1) sträng, och den misslyckas. Inte förvånande, den karaktären är U+2026 HORISONTAL ELLIPS , som inte har något enstaka ekvivalent tecken i ISO8859-1.

Du åtgärdade problemet genom att lägga till frågan ?charset=utf8 i ditt SQLAlchemy-anslutningsanrop:

import sqlalchemy
from sqlalchemy import create_engine, MetaData, Table

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

Avsnittet Databaswebbadresser i SQLAlchemy-dokumentationen berättar att en URL som börjar med mysql indikerar en MySQL-dialekt med mysql-python förare.

Följande avsnitt, Anpassad DBAPI connect()-argument , talar om för oss att frågeargument skickas till den underliggande DBAPI.

Så, vad gör mysql-python drivrutinsfabrikat av en parameter {charset:'utf8'} ? Avsnitt Funktioner och attribut i deras dokumentation står det om teckenuppsättningen attribut "...Om det finns, kommer anslutningsteckenuppsättningen att ändras till denna teckenuppsättning, om de inte är lika."

För att ta reda på vad anslutningsteckenuppsättningen betyder vänder vi oss till 10.1.4. Anslutningsteckenuppsättningar och sorteringar i referensmanualen för MySQL 5.6. För att göra en lång historia kort kan MySQL ha tolkat inkommande frågor som en kodning som skiljer sig från databasens teckenuppsättning och som skiljer sig från kodningen av de returnerade frågeresultaten.

Eftersom felmeddelandet du rapporterade ser ut som en Python snarare än ett SQL-felmeddelande, kommer jag att spekulera i att något i SQLAlchemy eller mysql-python försöker konvertera frågan till en standardanslutningskodning av latin-1 innan du skickar den. Det är detta som utlöser felet. Men frågesträngen ?charset=utf8 i din connect() samtalet ändrar anslutningskodningen och U+2026 HORIZONTAL ELLIPSIS kan ta sig igenom.

Uppdatering: du frågar också, "om jag tar bort teckenuppsättningsalternativet och sedan kodar beskrivningen med .encode('cp1252') kommer det att gå igenom fint. Hur kan en ellips komma igenom med cp1252 men inte unicode?"

kodningen cp1252 har ett horisontellt ellipstecken vid bytevärdet \x85 . Således är det möjligt att koda en Unicode-sträng som innehåller U+2026 HORIZONTAL ELLIPSIS till cp1252 utan fel.

Kom också ihåg att i Python är Unicode-strängar och bytesträngar två olika datatyper. Det är rimligt att spekulera i att MySQLdb kan ha en policy att endast skicka bytesträngar över en SQL-anslutning. Således skulle den koda en fråga som tas emot som en Unicode-sträng till en bytesträng, men lämnar en fråga som tas emot som en bytesträng ensam. (Detta är spekulationer, jag har inte tittat på källkoden.)

I spårningen du postade visar de två sista raderna (närmast där felet uppstår) metodnamnen literal , följt av unicode_literal . Det tenderar att stödja teorin att MySQLdb kodar frågan den tar emot som en Unicode-sträng till en bytesträng.

När du kodar frågesträngen själv, kringgår du den del av MySQLdb som gör denna kodning annorlunda. Observera dock att om du kodar frågesträngen annorlunda än vad MySQL-anslutningens teckenuppsättning kräver, kommer du att ha en kodningsfel och din text kommer sannolikt att lagras fel.



  1. MySQL:Åtkomst nekad för användaren 'test'@'localhost' (med lösenord:JA) förutom root-användare

  2. SQL-fråga för att hitta saknade rader mellan två relaterade tabeller

  3. MySQL startar inte när du uppgraderar OSX till Yosemite eller El Capitan

  4. Kan inte hitta microsoft.sqlserver.batchparser.dll