注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

蜻蜓点水 举重若轻

君子终日乾乾

 
 
 

日志

 
 

SQLObject 的中文编码问题及解决方案

2006-10-31 12:30:04|  分类: Python |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
问题出现: SQLObject 没有考虑到非 ASCII 编码集对 UnicodeCol 的影响


SQLObject 被誉为目前最为成熟的 Python ROM 工具, 在 TurboGears 里面被推荐为核心组件, 也令我着迷。所以我将其用于工作实践 (我基于 SQLObject/Cherrypy 的另一个轮子)。其中用到 UnicodeCol (列字段) 来存储中文字符。其表结构设计如下:

from sqlobject import SQLObject, UnicodeCol
from turbogears import database
hub = database.AutoConnectHub(config.uri)
class Foo(SQLObject):
    _connection = hub
    colX = UnicodeCol(length=20)
    colY = UnicodeCol(length=20)

发现在存储中文 Unicode 或者 utf-8 字符串时, 程序报告 Unicode 编解码错误, 尝试修改为普通的 StringCol, 仍然报错。


进入 SQLObject 源文件进行检查, 发现 SQLObject 使用 Python 安装时设置的默认编码集来对数据编码进行处理。而 Python 的默认编码集通常是 ascii 编码。


让 事情变得糟糕的原因是 SQLObject 的内部同时存在 "Unicode 到默认编码 (ascii)" 以及从 "默认编码 (ascii) 到 Unicode" 两个方向的编解码过程, 这实际上意味着无论输入字符是否为 Unicode (或 str), 存储格式无论是否为 Unicode (或 str), 我们都无法保证非 ascii 编码集的数据能够走完整个 SQLObject 内部流程, 能做 Unicode Encode 就无法 Unicode Decode 反之亦然! 因此非 ascii 编码, 包括中文、iso88591 等数据都无法正常使用 SQLObject。


这个问题令人不解, 作为开源软件几乎不可能犯这种相对低级的错误, Unicode 和 str 之间的转换只能是在 IO 接口处进行, 作为程序库在内部多次进行此类转换几乎是致命的。不知是作者有意为之 (改变默认编码集可以优雅地解决这个问题, 说明存在此种可能), 还是疏忽了。


修改 SQLObject 相关代码是解决途径, 这需要提交给作者。自己做分叉版本无非是另外一个世界中 Win32 程序员的弱智作风, 介于无论如何都是比较麻烦的事情, 我又是懒惰的程序员, 因此开始考虑通过将默认编码集从 ascii 替换到 utf-8 的方法来解决这个问题。


替换默认编码到 UTF-8

有一个关于正则表达式的笑话: "本来是想解决一个问题却引入了一堆问题"。为了解决 SQLObject 的困难, 却在解决方法上又碰到了钉子。


本来 sys 模块有一个 setdefaultencoding 接口, 待要用时却发现已经被 Python 的启动脚本 (setting.py) 删除了。通过社区, 找到了恢复这个接口的方法。就是 reload(sys) !


因此, 我在 Cherrypy Deamon Server 启动时增加了如下配置, 最终解决了 SQLObject 的编码问题:

import sys
if sys.getdefaultencoding() != 'utf-8':
    reload(sys)
    sys.setdefaultencoding('utf-8')

在其他 Cherrypy 或者 Python 的应用服务器架构中 (比如 TurboGears) 可以如法炮制。


延伸话题

因 为这次经历, 我阅读了一些 SQLObject 的源带码, 发现 SQLObject 的代码质量并不如我原来想象中那么优异, 比如许多 try all, Style 也略显混乱, 叙述方式冗长不够简洁。不是我个人喜欢的那种风格。但是抛开这些, SQLObject 经历了实践的检验, 在社区中有口皆碑, 是可靠的。


这件事情让我心有余悸, 同时因为 SQL 架构在集成性上不如 ZODB 更方便, 这让我开始考虑在 Gears 里面渗入 ZODB 以替代 ORM 的可能性。TurboGears Blog 也有相关的探讨, 说明 TG 的作者其实也是有意向的。然而 ROR like 的构架乃是以轻量级立身, 若引进 ZODB 便容易一发而不可收, 径直往 Zope/Plone 架构而去, 这是所有人所不愿看到的。然另辟蹊径也不是没有可能, 譬如直接使用 Zope 甚至 Plone 来做为 DBMS。目前我正在尝试这个轮子。
  评论这张
 
阅读(1282)| 评论(1)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017