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.
Комментариев нет:
Отправить комментарий