Как заставить SQLAlchemy правильно вставлять многоточие Unicode в таблицу mySQL?

Я пытаюсь проанализировать RSS-канал с помощью feedparser и вставить его в таблицу mySQL с помощью SQLAlchemy. Мне действительно удалось заставить это работать нормально, но сегодня в ленте был элемент с многоточием в описании, и я получаю следующую ошибку:

UnicodeEncodeError: кодек 'latin-1' не может кодировать символ u '\ u2026 'в позиции 35: порядковый номер не в диапазоне (256)

Если я добавлю в движок опцию convert_unicode = True, я смогу заставить вставку пройти, но многоточие не отображается, это просто странные символы. Кажется, это имеет смысл, поскольку, насколько мне известно, в latin-1 нет горизонтального многоточия. Даже если я установил кодировку utf-8, это, похоже, не имеет значения. Если я сделаю вставку с помощью phpmyadmin и добавлю многоточие, все пройдет нормально.

Я думаю, что просто не понимаю кодировки символов или то, как заставить SQLAlchemy использовать ту, которую я указываю. Кто-нибудь знает, как ввести текст без странных символов?

ОБНОВЛЕНИЕ

Я думаю, что понял это, но я не совсем уверен, почему это важно ...

Вот код :

import sys
import feedparser
import sqlalchemy
from sqlalchemy import create_engine, MetaData, Table

COMMON_CHANNEL_PROPERTIES = [
  ('Channel title:','title', None),
  ('Channel description:', 'description', 100),
  ('Channel URL:', 'link', None),
]

COMMON_ITEM_PROPERTIES = [
  ('Item title:', 'title', None),
  ('Item description:', 'description', 100),
  ('Item URL:', 'link', None),
]

INDENT = u' '*4

def feedinfo(url, output=sys.stdout):
  feed_data = feedparser.parse(url)
  channel, items = feed_data.feed, feed_data.entries

  #adding charset=utf8 here is what fixed the problem

  db = create_engine('mysql://user:pass@localhost/db?charset=utf8')
  metadata = MetaData(db)
  rssItems = Table('rss_items', metadata,autoload=True)
  i = rssItems.insert();

  for label, prop, trunc in COMMON_CHANNEL_PROPERTIES:
    value = channel[prop]
    if trunc:
      value = value[:trunc] + u'...'
    print >> output, label, value
  print >> output
  print >> output, "Feed items:"
  for item in items:
    i.execute({'title':item['title'], 'description': item['description'][:100]})
    for label, prop, trunc in COMMON_ITEM_PROPERTIES:
      value = item[prop]
      if trunc:
        value = value[:trunc] + u'...'
      print >> output, INDENT, label, value
    print >> output, INDENT, u'---'
  return

if __name__=="__main__":
  url = sys.argv[1]
  feedinfo(url)

Вот результат / трассировка выполнения кода без опции charset:

Channel title: [H]ardOCP News/Article Feed
Channel description: News/Article Feed for [H]ardOCP...
Channel URL: http://www.hardocp.com

Feed items:
     Item title: Windows 8 UI is Dropping the 'Start' Button
     Item description: After 15 years of occupying a place of honor on the desktop, the "Start" button will disappear from ...
     Item URL: http://www.hardocp.com/news/2012/02/05/windows_8_ui_dropping_lsquostartrsquo_button/
     ---
     Item title: Which Crashes More? Apple Apps or Android Apps
     Item description: A new study of smartphone apps between Android and Apple conducted over a two month period came up w...
     Item URL: http://www.hardocp.com/news/2012/02/05/which_crashes_more63_apple_apps_or_android/
     ---
Traceback (most recent call last):
  File "parse.py", line 47, in <module>
    feedinfo(url)
  File "parse.py", line 36, in feedinfo
    i.execute({'title':item['title'], 'description': item['description'][:100]})
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/sql/expression.py", line 2758, in execute
    return e._execute_clauseelement(self, multiparams, params)
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 2304, in _execute_clauseelement
    return connection._execute_clauseelement(elem, multiparams, params)
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 1538, in _execute_clauseelement
    compiled_sql, distilled_params
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 1639, in _execute_context
    context)
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/engine/default.py", line 330, in do_execute
    cursor.execute(statement, parameters)
  File "build/bdist.linux-i686/egg/MySQLdb/cursors.py", line 159, in execute
  File "build/bdist.linux-i686/egg/MySQLdb/connections.py", line 264, in literal
  File "build/bdist.linux-i686/egg/MySQLdb/connections.py", line 202, in unicode_literal
UnicodeEncodeError: 'latin-1' codec can't encode character u'\u2026' in position 35: ordinal not in range(256)

Похоже, что добавление кодировки в строку подключения mysql сделало это.Я полагаю, это по умолчанию latin-1? Я попытался установить флаг кодировки на content_engine на utf8, но ничего не сделал. Кто-нибудь знает, почему он будет использовать latin-1, когда для таблиц и полей установлено значение Unicode utf8? Я также пробовал кодировать элемент ['описание] с помощью .encode (' cp1252 ') перед его отправкой, и это сработало даже без добавления параметра charset в строку подключения. Это не должно было работать с latin-1, но, видимо, сработало? У меня есть решение, но я бы хотел получить ответ :)

16
задан kvedananda 6 February 2012 в 13:41
поделиться