/ / Грешно кодирани символи, когато изпращам utf8 кодирани символи от панда към mysql с latin-1 кодиране - python, mysql, pandas, encoding

Грешен кодиран знак, когато изпращам utf8 кодирани знаци от панда към mysql с кодиране на латиница-1 - python, mysql, pandas, кодиране

Получавам погрешно кодирани символи, когато изпращам utf8 кодирани символи от панда до mysql с латински-1 кодиране. Това е примерна стойност, която получавам в mysql:

Biquíni

Това е моят код:

df.breakdown_name = df.breakdown_name.str.encode("latin-1")

send_data(DB_ENGINE, MYSQL_USER, MYSQL_PASSWORD, MYSQL_HOST, MYSQL_PORT, MYSQL_DB, MYSQL_TABLE, df)

def send_data(db, db_user, db_password, db_host, db_port, db_name, db_table, df):
"""
Return data
1
"""
# print db
# print db_user
# print db_password
# print db_host
# print db_port
# print db_name
# print query[0:20]
SQL_ENGINE = "{db}://{db_user}:{db_password}@{db_host}:{db_port}/{db_name}?charset={encoding}".format(
db=db,
db_user=db_user,
db_password=db_password,
db_host=db_host,
db_port=db_port,
db_name=db_name,
encoding="latin1",
)
engine = create_engine(SQL_ENGINE)
df.to_sql(name=db_table,con=engine,schema="xxx",if_exists="append", index=False, chunksize=50)

Отговори:

1 за отговор № 1

Предполагам, че стойността на извадката трябва да бъде:

print u"Biquíni".encode("latin_1").decode("utf-8") # Biquíni

Така в кода си правите обратната трансформация:

print u"Biquíni".encode("utf-8").decode("latin_1") # Biquíni

Проблемът е, че когато прилагате веригата:

  1. Кодирайте unicode в "utf-8" байтове.
  2. Декодирайте тези байтове с всяко 1-байтово кодиране (като "latin_1").

за всеки не-ASCII unicode символ на входа, който "ще" винаги получавате грешни знаци на изхода. Това се случи, защото за такъв знак има поне 2-байтова стойност в "utf-8".

Нека разгледаме примери:

print ord(u"z") # 122 => ASCII
print repr(u"z".encode("utf-8")) # "z", 1 byte
print repr("z".decode("latin_1")) # u"z"

Както виждаме, за ASCII-символа всичко работи добре, но:

print ord(u"í") # 237 => non-ASCII

import unicodedata

print repr(u"í") # u"xed"
print unicodedata.name(u"xed") # LATIN SMALL LETTER I WITH ACUTE

print repr(u"xed".encode("utf-8")) # "xc3xad" => 2 bytes

print repr("xc3".decode("latin_1")) # u"xc3" - the 1st char
print repr("xad".decode("latin_1")) # u"xad" - the 2nd char

print unicodedata.name(u"xc3") # LATIN CAPITAL LETTER A WITH TILDE
print unicodedata.name(u"xad") # SOFT HYPHEN

Така че, в кода си за всеки не-ASCII символ след кодиране в "utf-8" получавате 2 байта, които след това се декодират "latin_1" в 2 знака и те не съответстват на първоначалния знак.

По този начин настоящата схема на вашата програма ще генерира нежелани резултати.
Предлагам да се използва същото кодиране за encode() и decode() стъпки в кода ви.