Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Jak uzyskać SQLAlchemy, aby poprawnie wstawić wielokropek Unicode do tabeli mySQL?

Komunikat o błędzie

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

wydaje się wskazywać, że jakiś kod języka Python próbuje przekonwertować znak \u2026 do łańcucha Latin-1 (ISO8859-1) i nie działa. Nic dziwnego, że ten znak to U+2026 POZIOMA ELIPSA , który nie ma jednego odpowiednika w ISO8859-1.

Naprawiłeś problem, dodając zapytanie ?charset=utf8 w wywołaniu połączenia SQLAlchemy:

import sqlalchemy
from sqlalchemy import create_engine, MetaData, Table

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

Sekcja URL bazy danych dokumentacji SQLAlchemy mówi nam, że adres URL zaczynający się od mysql wskazuje dialekt MySQL, używając mysql-python kierowca.

Poniższa sekcja, Niestandardowe DBAPI argumenty connect() , informuje nas, że argumenty zapytania są przekazywane do bazowego DBAPI.

Co więc oznacza mysql-python wykonanie sterownika z parametrem {charset:'utf8'} ? Sekcja Funkcje i atrybuty ich dokumentacji mówi o zestawie znaków atrybut "...Jeśli jest obecny, zestaw znaków połączenia zostanie zmieniony na ten zestaw znaków, jeśli nie są one równe."

Aby dowiedzieć się, co oznacza zestaw znaków połączenia, zwracamy się do 10.1.4. Zestawy znaków połączenia i sortowanie podręcznika MySQL 5.6. Krótko mówiąc, MySQL może interpretować przychodzące zapytania jako kodowanie inne niż zestaw znaków bazy danych i inne niż kodowanie zwróconych wyników zapytania.

Ponieważ zgłoszony komunikat o błędzie wygląda jak komunikat o błędzie Pythona, a nie SQL, będę spekulować, że coś w SQLAlchemy lub mysql-python próbuje przekonwertować zapytanie na domyślne kodowanie połączenia latin-1 przed wysłaniem. To jest przyczyną błędu. Jednak ciąg zapytania ?charset=utf8 w swoim connect() wywołanie zmienia kodowanie połączenia, a U+2026 HORIZONTAL ELIPSIS jest w stanie się przedostać.

Aktualizacja: pytasz również:„Jeśli usunę opcję zestawu znaków, a następnie zakoduję opis za pomocą .encode('cp1252'), wszystko będzie dobrze. Jak wielokropek może przejść przez cp1252, ale nie Unicode?”

kodowanie cp1252 ma poziomy znak wielokropka o wartości bajtu \x85 . W ten sposób można zakodować ciąg znaków Unicode zawierający U+2026 POZIOMA WIELOKROTKA do cp1252 bez błędu.

Pamiętaj też, że w Pythonie łańcuchy Unicode i łańcuchy bajtów to dwa różne typy danych. Rozsądne jest spekulowanie, że MySQLdb może mieć politykę wysyłania tylko ciągów bajtów przez połączenie SQL. W ten sposób zakoduje zapytanie odebrane jako ciąg Unicode w ciągu bajtów, ale pozostawi zapytanie odebrane jako ciąg bajtów. (To spekulacje, nie zajrzałem do kodu źródłowego.)

W przesłanym przez Ciebie śledzeniu, ostatnie dwie linie (najbliżej miejsca wystąpienia błędu) pokazują nazwy metod literal , po którym następuje unicode_literal . To potwierdza teorię, że MySQLdb koduje zapytanie, które otrzymuje jako ciąg Unicode w ciąg bajtów.

Kiedy sam kodujesz ciąg zapytania, pomijasz część MySQLdb, która wykonuje to kodowanie w inny sposób. Pamiętaj jednak, że jeśli zakodujesz ciąg zapytania w inny sposób, niż wymaga tego zestaw znaków połączenia MySQL, będziesz mieć niezgodność w kodowaniu, a tekst prawdopodobnie będzie zapisany nieprawidłowo.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Laravel Sail odbudowuje domyślną bazę danych

  2. Wstaw do tabeli, która ma myślnik w nazwie

  3. polecenie mysql do pokazywania aktualnych zmiennych konfiguracyjnych

  4. Błąd Django MySQL podczas tworzenia tabel

  5. CakePHP 3 - Parse Date z LocalStringFormat do poprawnego formatu SQL i poprawnej walidacji