Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Python: Базы данных > Помогите разобраться с отображением строк из MySQL


Автор: SergeiIv 6.10.2010, 12:19
В базе MySQL в табл sotrudn одна запись и в поле famili значение "Ивачев".
В my.ini:

[mysql]
default-character-set=utf8

И схема, и таблица, и столбец имеют кодировку utf8

Вот простенькая прога в Pytone:

import MySQLdb

Код

db= MySQLdb.connect(host='localhost', user='newuser', passwd='sssss', db='new_schema')
cursor= db.cursor()
cursor.execute("select famili from sotrudn")
for i in cursor.fetchall():
    print repr(i)
db.close()

Вот результат:

('??????',)

Подставляю в my.ini

[mysqld]
skip-character-set-client-handshake

получаю:

('\xd0\x98\xd0\xb2\xd0\xb0\xd1\x87\xd0\xb5\xd0\xb2',)

Все "битвы" проиграл. Может кто поможет )?

Автор: pythonwin 6.10.2010, 17:21
Цитата(SergeiIv @  6.10.2010,  15:19 Найти цитируемый пост)
Вот простенькая прога в Pytone:

 smile 
Код

# -*- coding: utf-8 -*-
db= MySQLdb.connect(host='localhost', user='newuser', passwd='sssss', db='new_schema')
cursor= db.cursor()
cursor.execute("select famili from sotrudn")
for i in cursor.fetchall():
    print repr(i.decode('cp866'))
db.close()


Думаю у вас стоит winXP и тогда наверное не нужно влазить в настройки mysql, а также при выводе на консоль необходимо учитывать, что там кодировка cp866

Автор: SergeiIv 8.10.2010, 07:39
Победил проблему так:
import MySQLdb
Код

#import _mysql

db= MySQLdb.connect(host='localhost', user='newuser', passwd='sptgw', db='new_schema')
cursor= db.cursor()
cursor.execute("select famili from sotrudn")
for i in cursor.fetchall():
     aa=eval(repr(i)[1:51])
     print i
     print aa

# хотя этот вариант работает:

a = '\xd0\x98\xd0\xb2\xd0\xb0\xd1\x87\xd0\xb5\xd0\xb2'
print(a.decode('utf-8'))
db.close()


результат:
Цитата

('\xd0\x98\xd0\xb2\xd0\xb0\xd1\x87\xd0\xb5\xd0\xb2',)
Ивачев
Ивачев


Конечно это искусственное решение проблемы, хотя сама проблема осталось и как решать её пока не знаю.
Хочу ещё заметить, что вся эта бодяга действительно по WinXP. 

Автор: SergeiIv 8.10.2010, 08:45
Но вот ещё какая тут вариация получилась ))):

Код

import MySQLdb

db= MySQLdb.connect(host='localhost', user='newuser', passwd='sptgw', db='new_schema')
cursor= db.cursor()
cursor.execute("select famili, name from sotrudn")

for i in cursor.fetchall():
     print i
     print i[0]+' '+i[1]

db.close()


результат:
Цитата


('\xd0\x98\xd0\xb2\xd0\xb0\xd1\x87\xd0\xb5\xd0\xb2', '\xd0\xa1\xd0\xb5\xd1\x80\xd0\xb3\xd0\xb5\xd0\xb9')
Ивачев Сергей


Т.е. при печать кортежа print кодировка определяется не понятно, а при извлечении элемента кортежа всё нормально. Почему так, пока вопрос.

Автор: av0000 8.10.2010, 10:07
Бли-и-ин!
Ну видно же, что возвращается, как и полагается, utf-8.

print для кортежей, списков итп "использует" repr, который не знает про кодировки и потому печатает байты.

Хочется строки -
Код

print u' '.join(i)
# или
print u'%s %s' % i

склеить через пробел, "заодно" можно конвертнуть в unicode. Вероятно первой-второй строке файла должно быть указание на кодировку самого .py файла -
Код

# -*- coding: utf-8 -*-

не помню в каких именно случаях автоконверт в unicode "падает" без явного указания кодировки.
Можно ещё сконвертить и после склейки -
Код

print unicode(' '.join(i), 'utf-8') # опять же лучше принудительно указать кодировку


Автор: SergeiIv 8.10.2010, 12:12
Цитата(av0000 @  8.10.2010,  13:07 Найти цитируемый пост)
print для кортежей, списков итп "использует" repr, который не знает про кодировки и потому печатает байты.

 это всё объясняет. Спасибо av0000.
Кстати
print u' '.join(i)
# или
print u'%s %s' % i

выдает ошибку:
UnicodeDecodeError: 'ascii' codec can't decode byte 0xd0 in position 0: ordinal not in range(128)
File "d:\PFiles\wxPython2.8 Docs and Demos\untitled-1.py", line 11, in <module>
  print u'%s %s' % i

а:
    print i[0]+' '+i[1]
    print unicode(' '.join(i), 'utf-8')
сработало правильно (и то и то)
но всё это только при наличии опции
skip-character-set-client-handshake
в My.ini

Автор: av0000 8.10.2010, 14:41
Цитата(SergeiIv @  8.10.2010,  12:12 Найти цитируемый пост)
print u'%s %s' % i

выдает ошибку:
UnicodeDecodeError: 'ascii' codec can't decode byte 0xd0 in position 0: ordinal not in range(128)


Вот этих нюансов я и не помню smile. Это последствия неправильной дефолтной кодовой страницы. Проявляется, в основном, под виндой.
Лечится указанием правильной кодировки консоли. Я знаю 2 способа. Второй подлиннее и нет под рукой примера, а первый - вот:
Код

# -*- coding: utf-8 -*-
import sys
reload(sys)
sys.setdefaultencoding('utf-8')

s = ('проверка', 'test')
print s
print u' '.join(s)
print u'%s %s' % s


Цитата(SergeiIv @  8.10.2010,  12:12 Найти цитируемый пост)
но всё это только при наличии опции
skip-character-set-client-handshake
в My.ini 

А вот тут уже надо "копать" настройки mysql-а. Т.е. если запретить мускулу перекодировку - он честно отдаёт utf-8. Я с ним дела не имею, но могу посоветовать поискать решение в мануалах по настройке django - где-то там такое попадалось.

Да, кстати, есть вероятность, что после указания sys.setdefaultencoding заработает и это... Что-то мне подсказывает, что он не может определить в какой кодировке отдавать данные и по-умолчанию их честно конвертит в вопросики.

Автор: SergeiIv 11.10.2010, 11:14
av0000 спасибо.
Вышеуказанный пример работает, но только с выставленным skip-character-set-client-handshake
в My.ini.

Автор: 22novimir 28.1.2013, 12:57
А у меня такой вот вопрос по базам. Залила на хостинг базу вроде раньше под ПХП работала супер и не кривлялась. А вот стала выборку писать на Питоне одни знаки вопроса. Что же случилось и где че прописать? В ПХП знаю, нужно прописать перед подключением к базе кое что по смене кодировки. А как в Питоне это реализовать? Спасибо!

Автор: lplsura 9.2.2013, 13:29
А интересно как вы базу из ПХП к Питону прикрутили:))) Вероятно у вас что то с кодировкой на сервере, напишите хостеру пусть сменит кодировку базы и все будет пучком. Некоторые хостеры разрешают это делать самому, а у некоторых нет. Можно и на лету менять кодировку, но это грузилово для сервера:)) Это для вас 22novimir!! smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)