Я отримую неправильно закодовані символи, коли надсилаю закодовані символи utf8 з панд в mysql з кодуванням Latin-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
Проблема полягає в тому, що коли ви реалізуєте ланцюг:
- Кодуйте unicode до "utf-8" байтів.
- Розшифруйте ці байти з будь-яким 1-байтовим кодуванням (наприклад, "latin_1").
для кожного символу unicode, який не є ASCII, на вході ви будете завжди отримувати неправильні символи на виході. Це трапляється, тому що для такого символу є принаймні 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"
на два символи, і вони не відповідають початковому символу.
Тим самим поточна схема вашої програми дасть небажані результати.
Я пропоную використовувати те саме кодування для encode()
і decode()
кроки у вашому коді.