Найти - Пользователи
Полная версия: Кодировка для запросов в БД
Начало » Python для новичков » Кодировка для запросов в БД
1 2 3 4
KarDer_Groom
o7412369815963
regall
Посмотрел в меню. В менюшке Кодировки->Кодировать в ANSI стоит. И при создании нового файла по умолчанию кодировка ANSI стоит.
Ага, значит можно сделать вывод, что загвоздка была именно в том что я писал в другой кодировки сам код. Следовательно в коде я указывал кодировку и пытался её сравнить с данными в БД в другой кодировки.

Вот только не пойму, файл сохраняется в ANSI кодировки, в коде cp1251 я его командой .decode('cp1251') декодировал в Юникод, но в БД у меня utf8. Получается “строка БД”==“строка в файле”.decode('cp1251')
Значит utf8==Unicode
Я прав?
pioner
Давайте вместе разбираться, а гуру поправят:
Кодировка - это инструкция как воспринимать последовательность байтов.
Вы писали в блокноте в кодировке cp1251. В исходнике указали utf8. В utf8 2 байта = 1 символ, но программы могут распознаватъ кодироку и в текстах utf8 латинские байты совпадают с латинскими байтами ANSI. Исходник прочитался, а то что в строке русскими буквами воспринялось…не понятно. Т.к. вы эти БАЙТЫ с помощью decode('cp1251') переводите в БАЙТЫ.
Слово “борщ”. Если кодек ‘cp1251’ преобразует из utf8, то на выходе будет 2 буквы вместо четырех первоначальных. В качестве одной буквы кодек возьмет 2 байта и выдаст 1 байт, т.к. в cp1251 буква=байт.
Т.е. на выходе “борщ” превратится в 2 байта. И база эти два байта воспримет как одну букву в utf8.
Если питон, каждый байт превратил в символ уникода то после decode('cp1251'), при условии что кодер воспринимает байты на входе как символы уникод, будет слово борщ в cp1251=4 байта=2 буквы в utf8…опять не сходится.
к стати “\xD0\xF3\xF1\xF1” = “русс” и это не уникод (я неправильно прошлый раз сказал) это 1251.
…вы не все показываете, наверное. что-бы воссоздать эксперимент мне надо mysql ставить, а так пока все вместо шашек.
Андрей Светлов
pioner
Все почти так и есть, с одним маленьким исключением: в utf-8 ascii символы (английские, пунктуация и проч) занимают 1 байт. Если старший бит - единица - то будет 2 байта и больше (для китайского и проч). Это в unicode все символы по 2 байта (или по 4, если питон был скомпилирован для ucs-4).
Андрей Светлов
KarDer_Groom
Во первых, в питоне есть два типа для строк. Если мы говорим о 2.х - то это str и unicode. Юникод - он и в Африке юникод, а с str есть особенности. Это по сути только набор байтов, как правильно сказал pioner. И, к сожалению, информации о кодировке в str нет. Поэтому если вы закодировали как cp1251 а ожидаете utf-8 - это будут разные строки, и они не совпадут.
Далее, есть еще и базы данных. Как правило, они хранят строки с указанием кодировок (на уровне БД или таблицы).
А еще существует DBAPI - стандарт для доступа из питона к БД. Есть много “драйверов” - реализаций этого стандарта для MySql, PostgreSql, MSSQL, Oracle и т.д. Все они немного разные, и каждая реализация является расширением DBAPI - добавляет нестандартные фичи, но при этом поддерживает базовый интерфейс. Так вот, если через DBAPI проходит str - он переправляется дальше к БД. Как именно - зависит от реализации DBAPI. Иногда это “просто напрямую”, бывает что str рассматривается как кодированный в “стандартной кодировке для Питона” - sys.getdefaultencoding - и преобразуется в то, что нужно БД. При этом, насколько я знаю, если давать unicode - то он всегда кодируется правильно (юникод однозначен, а кодировка БД известна драйверу).

P.S. В Python 2.x с кодировками есть путанница, которую починили в 3.x. Там переобозвали unicode в str, а старый str стал bytes. Так вот, bytes имеет только decode, а str - только encode. Советую пользоваться этим правилом и в двойке.
regall
Андрей Светлов
Все, что могу добавить о unicode и str в python 2.x: я, когда устанавливаю Python, в замечательном файлике lib/site.py (это на винде) делаю небольшую правку: в функции def setencoding() заменяю
    encoding = "ascii" # Default value set by _PyUnicode_Init()
на
    encoding = "utf-8" # Default value set by _PyUnicode_Init()
Это мне снимает очень множество проблем, какие возникают с этими двумя функциями (и часто в работе с доп. библиотеками), как и описал выше Андрей Светлов
pyuser
regall
Код:
encoding = “utf-8” # Default value set by _PyUnicode_Init()
уж если править, то не эту строку, а следующую (if 0: заменить на if 1:)
в одной из веток этого форума обсуждались “прелести” использования UTF-8 под win32. Часть проблем действительно исчезает, но появляются другие :-(
когда-то давно я тоже первым делом, после установки питона, правил файл site.py (замена указана выше), но потом избавился от этой вредной привычки, поскольку эта правка не избавляла от проблем, а наоборот их добавляла ИМХО, не было абсолютно ни какой уверенности в том, что скрипт, работающий на моем ПК будет корректно работать на другом
regall
pyuser
Часть проблем действительно исчезает, но появляются другие :-(
У меня других проблем не появлялось, только решались старые, может мне просто везет =)
pyuser
не было абсолютно ни какой уверенности в том, что скрипт, работающий на моем ПК
Естественно. например для проектов на Zope 3 такая замена для меня просто необходимость. На своем хостинге такую замену делаем по любому, если клиент хостится не у нас - указываем, что эту замену следует сделать, и где ее сделать…
KarDer_Groom
Ну в принципе понял, с кодировками.
Ещё понял что надо быть внимательнее. В Notepad++ поставил utf8 по умолчанию .decode('cp1251') убрал, всё работает.

pioner
Да, действительно это так “\xD0\xF3\xF1\xF1” == “русс” я это для примера кинул, не думал что кто-то будет проверять. \xD0\xF3\xF1\xF1 было только для визуального анализа. Извините если ввел кого в заблуждение.

regall
pyuser написал:

не было абсолютно ни какой уверенности в том, что скрипт, работающий на моем ПК
Согласен.
В site.py менять не хочу, надо учиться изначально делать всё так чтоб у всех работало, ведь после меня, я надеюсь эта программа ещё пригодится, и чтоб не искали как я сейчас они потом ответа на вопрос, а почему не работает??!! (((
Был момент, когда написал несколько полезных прог, для себя. Но они оказались бы полезными и моему другу, я на своём ПК использовал их бес проблем, но вот незадача, другу кинул, а у него “Error”, походу при компеляции библиотеки не вложил или что-то подобное - (Уже не важно.) После этого стараюсь всё делать чтоб и у людей в далёкой нигерии работало как часы.
severum
Здравствуйте. У меня та же похоже проблема, но я прочитав ничего не понял )

mySQL стоит локально. MySQL charset: UTF-8 Unicode (utf8)
таблица innoDB utf8_general_ci

код примерно как у всех
# -*- coding: UTF-8 -*-`
import MySQLdb

self.db = MySQLdb.connect(host=host, user=user, passwd=password, db=db)
print self.db.character_set_name()
self.c = self.db.cursor()
self.c.execute(“INSERT….”)

Файл в формате utf-8(без BOM)

строчка print self.db.character_set_name() пишет что latin1

self.c.execute(“INSERT….”) не ругается, но записывает в базу вместо русского слова “тест” - тест

есть добавить u
self.c.execute(u“INSERT….”) то ругается:
UnicodeEncodeError: ‘latin-1’ codec can't encode characters in position 158-161: ordinal not in range(256)
dimabest
надо указать правильную кодировку соединения вместо latin1

self.db = MySQLdb.connect(host=host, user=user, passwd=password, db=db, charset='utf8')
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB