views:

104

answers:

2

I retrieved the data encoded in big5 from database,and I want to send the data as email of html content, the code is like this:

html += """<tr><td>"""        
html += unicode(rs[0], 'big5') # rs[0] is data encoded in big5

I run the script, but the error raised: UnicodeDecodeError: 'ascii' codec can't decode byte...... However, I tried the code in interactive python command line, there are no errors raised, could you give me the clue?

+2  A: 

If html is not already a unicode object but a normal string, it is converted to unicode when it is concatenated with the converted version of rs[0]. If html now contains special characters you can get a unicode error.

So the other contents of html also need to be correctly decoded to unicode. If the special characters come from string literals, you could use unicode literals (like u"abcä") instead.

sth
So what is the encoding of html shall I set with, so the html content displayed properly in mail?
e.b.white
@zhangzhong: You should use the encoding the HTML is encoded in. Only you can know what encoding that is, but if its the same as the other data its probably 'big5'.
sth
+1  A: 

Your call to unicode() is working correctly. It is the concatenation, which is adding a unicode object to a byte string, that is causing trouble. If you change the first line to u'''<tr><td>''', (or u'<tr><td>') it should work fine.

Edit: This means your error lies in the data that is already in html by the time python reaches this snippet:

>>> '\x9f<tr><td>' + unicode('\xc3\x60', 'big5')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0x9f in position 0: ordinal not in range(128)
>>> u'\x9f<tr><td>' + unicode('\xc3\x60', 'big5')
u'\x9f<tr><td>\u56a5'
>>> 
jcdyer
You should always deal with unicode objects when possible. Decode input to unicode as soon as you can. Encode output to a specific encoding (utf-8, for instance) as late as you can. Use `codecs.open()` instead of the built-in `open()`, whenever possible.
jcdyer