db = MySQLdb.connect(user = 'user',
passwd = 'p4assw0rd',
db = 'db',
charset = 'koi8r')пакет отказывается работать, вываливая трейсбэк:Traceback (most recent call last): File "./myapp.py", line 559, inЯ знаю, что в MySQL приняты названия кодировок, из которых выкинуты минусы. Однако, если указать кодировку без минуса, то пакет всё равно отказывается работать, выдавая несколько другой трейсбэк:charset = 'koi8-r') File "/usr/local/lib/python2.7/site-packages/MySQL_python-1.2.3-py2.7-freebsd-8.2-RELEASE-p4-amd64.egg/MySQLdb/__init__.py", line 81, in Connect return Connection(*args, **kwargs) File "/usr/local/lib/python2.7/site-packages/MySQL_python-1.2.3-py2.7-freebsd-8.2-RELEASE-p4-amd64.egg/MySQLdb/connections.py", line 215, in __init__ self.set_character_set(charset) File "/usr/local/lib/python2.7/site-packages/MySQL_python-1.2.3-py2.7-freebsd-8.2-RELEASE-p4-amd64.egg/MySQLdb/connections.py", line 294, in set_character_set super(Connection, self).set_character_set(charset) _mysql_exceptions.OperationalError: (2019, "Can't initialize character set koi8-r (path: /usr/local/share/mysql/charsets/)")
Traceback (most recent call last): File "./myapp.py", line 612, inЧто характерно, для кодировки UTF-8 один из вариантов написания всё-же работает. Почитал, что об этом пишут в интернете. Один умный анонимный товарищ объяснил ситуацию так:merge_lists(list1, list2) File "./myapp.py", line 576, in merge_lists value = myfunction(list['key']) File "./myapp.py", line 514, in myfunction WHERE param = %s''', (value,)) File "/usr/local/lib/python2.7/site-packages/MySQL_python-1.2.3-py2.7-freebsd-8.2-RELEASE-p4-amd64.egg/MySQLdb/cursors.py", line 159, in execute query = query % db.literal(args) File "/usr/local/lib/python2.7/site-packages/MySQL_python-1.2.3-py2.7-freebsd-8.2-RELEASE-p4-amd64.egg/MySQLdb/connections.py", line 264, in literal return self.escape(o, self.encoders) File "/usr/local/lib/python2.7/site-packages/MySQL_python-1.2.3-py2.7-freebsd-8.2-RELEASE-p4-amd64.egg/MySQLdb/connections.py", line 202, in unicode_literal return db.literal(u.encode(unicode_literal.charset)) LookupError: unknown encoding: koi8r
А не MySQLdb ли там у Вас крутится?Это подтвердило мои собственные догадки. С момента написания этого высказывания прошло уже почти 5 лет, но ничего не изменилось. Видимо, это не нужно ни пользователям модуля, ни его разработчикам. Честно говоря, мне тоже не нужно - если бы у меня была возможность выбора, то я бы выбрал UTF-8, но у меня такой возможности не было.
если да - то тут две проблемы:
1. В mysql принято считать, что они лучше знают названия кодировок.
2. Модуль MySQLdb для питона считает, что в mysql действительно знают названия кодировок и верит,
что python в курсе, что кодировка KOI8-R называется "koi8r", хотя это далеко не так.
В модуле codecs python'а кодировка KOI8-R называется "koi8-r", что вообще-то соответствует стандарту.
python любит кодировать все строки в unicode. После чего, если они пытаются передаться в mysql, модуль MySQLdb
перекодирует из unicode в кодировку, установленную для соединения. А там 'koi8r', вот и ошибка вылетает.
Это лечится отстрелом авторов модуля MySQLdb.
Хотя впрочем, можно и всех mysqlистых ребят...
Отредактируем модуль connections.py, входящий в пакет MySQLdb:
# vi /usr/local/lib/python2.7/site-packages/MySQL_python-1.2.3-py2.7-freebsd-8.2-RELEASE-p4-amd64.egg/MySQLdb/connections.pyИ отредактируем метод set_character_set, как показано ниже:
def set_character_set(self, charset):
"""Set the connection character set to charset. The character
set can only be changed in MySQL-4.1 and newer. If you try
to change the character set from the current value in an
older version, NotSupportedError will be raised."""
mysql_charset = charset.replace('-', '')
if self.character_set_name() != mysql_charset:
try:
super(Connection, self).set_character_set(mysql_charset)
except AttributeError:
if self._server_version < (4, 1):
raise NotSupportedError("server is too old to set charset")
self.query('SET NAMES %s' % mysql_charset)
self.store_result()
self.string_decoder.charset = charset
self.unicode_literal.charset = charsetПересобирём модуль, чтобы им можно было пользоваться:# python -m compileall /usr/local/lib/python2.7/site-packages/MySQL_python-1.2.3-py2.7-freebsd-8.2-RELEASE-p4-amd64.egg/MySQLdb/connections.pyТеперь откроем файл cursors.py:
# vi /usr/local/lib/python2.7/site-packages/MySQL_python-1.2.3-py2.7-freebsd-8.2-RELEASE-p4-amd64.egg/MySQLdb/cursor.pyи добавим метод character_set_name() в класс BaseCursor:
def character_set_name():
db = self._get_db()
charset = db.character_set_name()
map = {'koi8r': 'koi8-r', 'koi8u': 'koi8-u'}
return map.get(charset.lower(), charset)
А во всех следующих ниже методах заменим строкиdb = self._get_db() charset = db.character_set_name()на строку:
charset = self.character_set_name()И перекомпилируем модуль:
# python -m compileall /usr/local/lib/python2.7/site-packages/MySQL_python-1.2.3-py2.7-freebsd-8.2-RELEASE-p4-amd64.egg/MySQLdb/cursors.pyС такими костылями всё работает нормально, во всяком случае на ошибки я при этом не натыкался. При необходимости можно добавить дополнительные отображения названий кодировок в хэш map.
Комментариев нет:
Отправить комментарий