当前位置: 首页 > 面试题库 >

如何获得SQLAlchemy来将Unicode省略号正确插入到mySQL表中?

邢冷勋
2023-03-14
问题内容

我正在尝试使用feedparser解析RSS
feed,并使用SQLAlchemy将其插入到mySQL表中。实际上,我能够使它运行得很好,但是今天,提要中有一个描述中带有省略号的项目,并且出现以下错误:

UnicodeEncodeError:’latin-1’编解码器无法在位置35编码字符u’\ u2026’:序数不在范围内(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,但没有执行任何操作。有人知道为什么在将表和字段设置为utf8
unicode时会使用latin-1吗?我还尝试在发送之前使用.encode(’cp1252’)编码item
[‘description],即使没有在连接字符串中添加charset选项,效果也很好。那不应该与latin-1一起使用,但是显然可以吗?我有解决方案,但希望得到一个答案:)


问题答案:

错误讯息

UnicodeEncodeError: 'latin-1' codec can't encode character u'\u2026' 
in position 35: ordinal not in range(256)

似乎表明某些Python语言代码正在尝试将字符\u2026转换为Latin-1(ISO8859-1)字符串,但操作失败。毫不奇怪,该字符为U+2026 HORIZONTAL ELLIPSIS,在ISO8859-1中没有单个等效字符。

您通过?charset=utf8在SQLAlchemy连接调用中添加查询来解决此问题:

import sqlalchemy
from sqlalchemy import create_engine, MetaData, Table

db = create_engine('mysql://user:pass@localhost/db?charset=utf8')

SQLAlchemy文档的 Database
Urls

部分告诉我们mysql,使用mysql-python驱动程序的URL开头表示MySQL语言。

下一节“ 自定义DBAPI
connect()arguments
”告诉我们将查询参数传递给基础DBAPI。

那么,mysql-python驱动程序对参数做了{charset: 'utf8'}什么?其文档的“ 功能和属性
”部分对charset属性说:“ …如果存在,则连接字符集如果不相等,则将更改为该字符集。”

为了找出连接字符集的含义,我们转向
10.1.4。
MySQL 5.6参考手册的
连接字符集和排序规则 。长话短说,MySQL可以将传入的查询解释为与数据库字符集不同的编码,并且与返回的查询结果的编码不同。

由于您报告的错误消息看起来像是Python而不是SQL错误消息,因此我推测SQLAlchemy或mysql-
python中的某些内容正在尝试latin-1在发送查询之前将查询转换为默认的连接编码。这就是触发错误的原因。但是,?charset=utf8connect()呼叫中的查询字符串会更改连接编码,并且U+2026 HORIZONTAL ELLIPSIS能够通过。

更新:
您还会问:“如果我删除字符集选项,然后使用.encode(’cp1252’)对描述进行编码,它将顺利通过。省略号如何能够通过cp1252而不通过unicode进行编码?”

该编码cp1252在字节值处具有水平省略号字符\x85。因此,可以将包含U+2026 HORIZONTAL ELLIPSIScp1252的Unicode字符串编码为无错误。

还要记住,在Python中,Unicode字符串和字节字符串是两种不同的数据类型。可以合理地推测MySQLdb可能具有通过SQL连接仅发送字节字符串的策略。因此,它将把以Unicode字符串接收的查询编码为字节字符串,但将仅留下以字节字符串接收的查询。(这是推测,我没有看过源代码。)

在您发布的回溯中,最后两行(最接近错误发生的位置)显示方法名称
literal,后跟unicode_literal。这倾向于支持MySQLdb将以Unicode字符串形式接收的查询编码为字节字符串的理论。

当您自己对查询字符串进行编码时,您将绕过MySQLdb进行编码方式不同的部分。但是请注意,如果您对查询字符串的编码方式与MySQL连接charset所要求的编码方式不同,那么您将出现编码不匹配的情况,并且您的文本可能会存储错误。



 类似资料:
  • 问题内容: 我正在尝试仅显示文本的前5行。问题在于文本的设置方式是一个div中的多个标签,例如 但是在这种情况下它们都不起作用,在这种情况下,我希望在最后一行的最后一个单词之后加上省略号,即使它没有到达行尾,也有多个标签。 我在Angular中使用JavaScript。 问题答案: 是的,您可以使用一些插件,但是编写自己的逻辑并不难。基本概念是不断减少文本的数量,直到适合为止。这听起来很昂贵,但实

  • 问题内容: 好的,所以我一直在研究Steam Web API,我将其中一个值存储在名为的变量中。当我使用此代码片段将其插入到mysql数据库中时,它会插入一个与存储在变量中不同的整数。 返回真实的int,回显它也是如此。不太确定这里发生了什么,我们将不胜感激。 问题答案: 可能是因为您将查询用双引号引起来,但是变量用单引号引起来,因此将其视为文字,并且如果该列是int,则将得到0。 尝试这个: 另

  • 问题内容: 我有一个具有弹性布局的网页,如果调整了浏览器窗口的大小,该网页的宽度就会改变。 在此布局中,标题()的长度是可变的(实际上是我无法控制的博客文章的标题)。当前-如果它们比窗口宽-分为两行。 是否有一种经过测试的(跨浏览器)优雅的解决方案(例如jQuery),可以缩短该标题标签的innerHTML,并在文本太宽而无法在当前屏幕/容器宽度? 问题答案: 我有一个可以在FF3,Safari和

  • 本文向大家介绍我们如何将数据插入MySQL表?,包括了我们如何将数据插入MySQL表?的使用技巧和注意事项,需要的朋友参考一下 要将数据插入到MySQL表中,我们需要使用INSERT INTO命令。我们必须在INSERT INTO命令中为表的所有列指定值。 语法 示例 假设我们有一个名为“ Student”的表,其中包含三列“ RollNo”,“ Name”和“ Class”,然后借助以下查询,我

  • 我刚刚发现,即使省略了参数上的注释,Spring仍然能够绑定它。 有人能指出澄清这种行为的文档吗?我一直认为是绑定工作所必需的。 谢谢

  • 问题内容: 我正在使用。我想找到一个与此CSS类等效的SVG,如果文本从其包含的div中流出,则会添加省略号: 这是我的SVG: 它的生成如下: 当前文本溢出并且与rect元素重叠。 我有什么办法可以说:“如果文本大于特定宽度,则将其裁剪并添加省略号”? 问题答案: 我不知道SVG的等效CSS类,但是您可以用来将HTML嵌入SVG。这使您可以使用此功能,并且通常更灵活(例如,您可以轻松进行自动换行

  • 我正在尝试创建一个检查整数的函数,并将继续循环,直到用户正确输入17或更高的整数。但是,如果我输入错误的输入,例如“K”或“

  • 问题内容: 我正在使用Python 在mysql中运行查询 运行查询后,我想知道该行的主键。我知道有查询 但是我不确定它是否可以与插入忽略一起使用 做这个的最好方式是什么? 问题答案: 文档的说: 如果使用INSERT IGNORE并且忽略该行,则AUTO_INCREMENT计数器不会增加,并且LAST_INSERT_ID()返回0,这表明没有插入行。 知道了这一点,您可以将其分为多个步骤: 插入