2010-08-15 71 views
7

所以我有这个页面:如何检查一个Python unicode字符串以查看它*实际*是否是正确的Unicode?

http://hub.iis.sinica.edu.tw/cytoHubba/

显然,它是各种搞砸,因为它得到正确解码,但是当我尝试将其保存在Postgres里,我得到:

DatabaseError: invalid byte sequence for encoding "UTF8": 0xedbdbf 

的数据库在此之后掀起轩然大波,并拒绝没有回滚的任何事情,这将会有点难以发布(长篇故事)。有没有办法让我来检查它是否会在它碰到数据库之前发生? source.encode(“utf-8”)工作顺利,所以我不知道发生了什么事...

+0

你确定你的连接设置为使用UTF-8吗? – Wolph 2010-08-15 12:50:10

+0

是的,30万其他网页加入就好了,只是这一个失败... – 2010-08-15 13:23:41

回答

9

有一个错误在python 2.x只是固定的python 3.x.事实上,这个bug甚至在OS X的iconv中(但不是glibc的)。

发生了什么:

Python 2。X不承认UTF8代理对[1]为无效(这是你的字符序列是什么)

应该是所有的需要:

foo.decode('utf8').encode('utf8') 

但由于他们是这个bug没有修复,它没有捕获代理对。

在Python 2.x中试试这个,然后在3.X:

b'\xed\xbd\xbf'.decode('utf8') 

它将在后者抛出一个错误(正确)。他们也没有修复它在2.x分支。参见[2]和[3]更多信息

[1] http://tools.ietf.org/html/rfc3629#section-4

[2] http://bugs.python.org/issue9133

[3] http://bugs.python.org/issue8271#msg102209

+0

谢谢,这是我怀疑的。选择正确。 – 2010-08-19 09:47:44

+0

没问题。我正在尝试做更多或更少的工作,以便在COPY到postgres时过滤我的数据。我最终做的只是让它失败,并根据错误输出筛选出单个行。它基于pgloader中复制代码的工作原理http://pgfoundry.org/projects/pgloader/ – mikelikespie 2010-08-19 10:17:33

+0

无关联:如果您想修复代理对:'u'[\ ud83d \ ude42]'。编码('utf-16','surrogatepass')。decode('utf-16')= u'[\ U0001f642]'' – jfs 2016-05-01 12:59:35

1

Python unicode object是一个Unicode代码点序列,根据定义合适的unicode。 python str字符串是一个字节序列,可能是使用特定编码(UTF-8,Latin-1,Big5,...)编码的Unicode字符。

第一个问题是sourceunicode对象还是str字符串。 那source.encode("utf-8")工作只是意味着你可以可以转换source为UTF-8编码的字符串,但你是否做它之前,你将它传递给数据库函数?数据库似乎预计它的输入将用UTF-8编码,并且抱怨source.decode("utf-8")的等效失败。

如果sourceunicode对象,应该将它传递给数据库之前被编码成UTF-8:

source = u'abc' 
call_db(source.encode('utf-8')) 

如果sourcestr编码成UTF-8以外,你应该别的东西解码该编码,然后编码结果Unicode对象为UTF-8:

source = 'abc' 
call_db(source.decode('Big5').encode('utf-8')) 
+1

对不起,我应该澄清。源代码是一个unicode对象,在Python中被编码得很好,当我尝试将它发送到postgres时,事情会中断... – 2010-08-15 13:27:27

0

究竟你在做什么?内容确实解码罚款utf-8

>>> import urllib 
>>> webcontent = urllib.urlopen("http://hub.iis.sinica.edu.tw/cytoHubba/").read() 
>>> unicodecontent = webcontent.decode("utf-8") 
>>> type(webcontent) 
<type 'str'> 
>>> type(unicodecontent) 
<type 'unicode'> 
>>> type(unicodecontent.encode("utf-8")) 
<type 'str'> 

确保你理解Unicode字符串和UTF-8编码字符串之间的区别,虽然。你需要发送到数据库的是unicodecontent.encode("utf-8")(与webcontent相同,但是你解码以验证你的不是在你的源中有无效的字节序列)。

我的确如WoLpH所说的检查数据库和数据库连接的设置。

+0

我使用Django,它正确编码所有东西,但它的postgres决定编码(或编码字符串)由于某种原因,我的工作很糟糕......我在Python中的所有工作都是有效的,这就是为什么我无法检测到它。也许这是一个postgres错误? – 2010-08-15 13:26:45

0

最后,我选择了解决这个问题,使用Django的事务管理捕获错误并回滚事务。我很神秘,为什么会发生,虽然...

0

为了解决我的Django的类似问题/ postgress我现在做这样的事情

class SafeTextField(models.TextField) 
    def get_prep_value(self, value): 
     encoded = base64.encodestring(value).strip() 
     return super(SafeTextField, self).get_prep_value(encoded) 
    def to_python(self, value): 
     decoded = base64.decodestring(value) 
     return super(SafeTextField, self).to_python(decoded)