python 编码问题

Jave.Lin 2013-08-05 03:27:00
源代码:

#coding="utf-8"

import sys
import MySQLdb
import types
import codecs

conn = MySQLdb.connect(host='...', user='...', passwd='...', db='...', port=8001, charset='gbk')
cursor = conn.cursor(cursorclass=MySQLdb.cursors.DictCursor)

n = cursor.execute("select * from t_award_info limit 2");
fAllData = cursor.fetchall();
print "fAllData:\n" + str(fAllData);

for row in fAllData:
for r in row:
k = r.encode("gbk")
print k
print k + " = " + (str(row[k]).encode("gbk") if (row[k] is types.StringType) else str(row[k]).encode("gbk"))

cursor.close();
conn.close();


运行后报错:
Traceback (most recent call last):
File "F:\WorkFiles\Study\python\test_mysql\TestMySql.py", line 21, in <module>
print k + " = " + (str(row[k]).encode("gbk") if (row[k] is types.StringType) else str(row[k]).encode("gbk"))
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-2: ordinal not in range(128)

就这行报错:
print k + " = " + (str(row[k]).encode("gbk") if (row[k] is types.StringType) else str(row[k]).encode("gbk"))
...全文
383 31 打赏 收藏 转发到动态 举报
写回复
用AI写文章
31 条回复
切换为时间正序
请发表友善的回复…
发表回复
panghuhu250 2013-08-07
  • 打赏
  • 举报
回复
我的也是2.7.5,用type(..)==unicode没问题。你列的row[k]这些类型,只有unicode不能用str,所以#21楼的办法应该可以,如果你弄明白为什么unicode会引起NameError的话。 还可以用try:

#... now you have k, row[k]
  try:
    k += str(row[k])
  except UnicodeEncodeError:
    k += row[k]
中文注释的问题,#5楼就提到了。
Jave.Lin 2013-08-07
  • 打赏
  • 举报
回复
或说,你们都可以在.py文件中写上非英文的注释,怎么我的不可以; 如果写上非英文注释,运行就报字符集编码错误; 我用notepad++写.py,然后直接:cmd 调之; 是否与IDE;
Jave.Lin 2013-08-07
  • 打赏
  • 举报
回复
引用 24 楼 panghuhu250 的回复:
你的python版本是什么?看你可以用"print ...",我以为是python2,但unicode又不存在(unicode是python2.0加上的)? 引起错误的row[k]到底是什么类型:自己定义的类还是unicode字符串?
我安装的python是2.7.5版本 row[k]是基础数据类型的数据;(int,string,char,long,float)都有可能; row[k]是mysql 数据库中,某个表中的某个记录[k](名称为K的列对应的数据)
panghuhu250 2013-08-07
  • 打赏
  • 举报
回复
你的python版本是什么?看你可以用"print ...",我以为是python2,但unicode又不存在(unicode是python2.0加上的)? 引起错误的row[k]到底是什么类型:自己定义的类还是unicode字符串?
Jave.Lin 2013-08-07
  • 打赏
  • 举报
回复
其实我这边问题,重现,你可以,试一下: 用python MySqldb fetch一些数据; 并直接打印现来是没有问题的; 说明:print 内置方法处理还是有一些统一的方式,可以将任何对象转成字符串,并出来到控制台; 但如果说,想要自己先fetch出来的表,每个记录数据,都组装字符串(我这边就是想装成,xml,而且是自己定义格式内容的xml,我在网上搜索到有py xml导出导入库,但不适合我,因为导出都是标准的xml;); 再把这些字符串保存成文件; 就是将一些后台数据库的配置数据;写一个py脚本,导出客户端需要的.xml配置;压缩打包; 但随知道,py字符串转编码还这么麻烦滴;最大原因就是不熟悉;
Jave.Lin 2013-08-07
  • 打赏
  • 举报
回复
引用 21 楼 panghuhu250 的回复:
row[k]都可能是什么类型?把unicode字符串单独处理,其它的用str行不行: k + (row[k] if type(row[k]) == unicode else str(row[k]))

for row in fAllData:
	for r in row:
		k = r.encode("gbk")
		temp1 = row[k]
		temp2 = None
		if(type(temp1) is types.StringType): # is string, translate coding
			temp2 = temp1.encode("gbk") # translate coding here
		else:
			# rase exception : UnicodeEncodeError: 
			#'ascii' codec can't encode characters in position 0-2: ordinal not in range(128)
			temp2 = str(row[k])	# not a string, then convert it 注意这是里报错
		print temp2;

for row in fAllData:
	for r in row:
		k = r.encode("gbk")
		temp1 = row[k]
		temp2 = None
		if(type(temp1) == unicode): # is string, translate coding 这里直接报错:NameError: Name 'unicode' is not defined
			temp2 = temp1.encode("gbk") # translate coding here
		else:
			# rase exception : UnicodeEncodeError: 
			#'ascii' codec can't encode characters in position 0-2: ordinal not in range(128)
			temp2 = str(row[k])	# not a string, then convert it
		print temp2;
panghuhu250 2013-08-07
  • 打赏
  • 举报
回复
row[k]都可能是什么类型?把unicode字符串单独处理,其它的用str行不行: k + (row[k] if type(row[k]) == unicode else str(row[k]))
Jave.Lin 2013-08-07
  • 打赏
  • 举报
回复
引用 19 楼 panghuhu250 的回复:
把obj转变为str,与把str编码是两件事,为什么要把他们合在一起? obj ----> str(obj) ----> encode('xxx') object unicode desired encode 这样,obj只要知道怎么用unicode表示自己。 你的例子中,为什么不直接:
print k + "=" row[k]
或者转为unicode:
print k + "=" row[k].decode('gbk')
你说的这里方法都我问之前就试过了; 不是所有对象都可以,直接.decode或是.encode,要字符串才有该两个方法(除了自己写或是偶然有这个定义方法的类); k是字符串,而python中是含有:字符串“+”号操作符,作用是:字符串相连; 而row[k]的数据不一定是字符串。直接调用.decode或是.encode就会报错;
panghuhu250 2013-08-07
  • 打赏
  • 举报
回复
引用 28 楼 linjf520 的回复:
想不到unicode编码的字符串还不可以用str(unicodeString);
可能的话改用python3也是一个办法。python3中没了string和unicode的区分,所以str('寒')没问题,就是返回'寒'。
Jave.Lin 2013-08-07
  • 打赏
  • 举报
回复
引用 29 楼 maniachhz 的回复:
按楼主的需求,可以先把全部字符转化成unicode类型,然后再编码, 无需关注是否是string类型.

#coding="utf-8"
 
import sys
import MySQLdb
#import codecs
#import types
import chardet # 需要使用chardet来识别每列的编码.
 
conn = MySQLdb.connect(host='...', user='...', passwd='...', db='...', port=8001, charset='gbk')
cursor = conn.cursor(cursorclass=MySQLdb.cursors.DictCursor)
 
n = cursor.execute("select * from t_award_info limit 2");
fAllData = cursor.fetchall();
print "fAllData:\n" + str(fAllData);
 
for row in fAllData:
    for r in row:
        k = r.encode("gbk")
        print k
        column_encode = chardet.detect(row[k])['encoding'] #先获得编码
        print k + " = " + row[k].decode(column_encode).encode('gbk') # 再编码成gbk
     
cursor.close();
conn.close();
我之前就是想用chardet模块; 但安装不了; setup.py install时,报,from setupTools import setup no module setup 之类的; 其它模块都可以安装,为啥就这个chardet不行; 等会再去下另一个chardet试试; 可能与版本有关;因为chardet的高级版可能py3我用的是py2
maniachhz 2013-08-07
  • 打赏
  • 举报
回复
按楼主的需求,可以先把全部字符转化成unicode类型,然后再编码, 无需关注是否是string类型.

#coding="utf-8"
 
import sys
import MySQLdb
#import codecs
#import types
import chardet # 需要使用chardet来识别每列的编码.
 
conn = MySQLdb.connect(host='...', user='...', passwd='...', db='...', port=8001, charset='gbk')
cursor = conn.cursor(cursorclass=MySQLdb.cursors.DictCursor)
 
n = cursor.execute("select * from t_award_info limit 2");
fAllData = cursor.fetchall();
print "fAllData:\n" + str(fAllData);
 
for row in fAllData:
    for r in row:
        k = r.encode("gbk")
        print k
        column_encode = chardet.detect(row[k])['encoding'] #先获得编码
        print k + " = " + row[k].decode(column_encode).encode('gbk') # 再编码成gbk
     
cursor.close();
conn.close();
Jave.Lin 2013-08-07
  • 打赏
  • 举报
回复
引用 27 楼 panghuhu250 的回复:
我的也是2.7.5,用type(..)==unicode没问题。你列的row[k]这些类型,只有unicode不能用str,所以#21楼的办法应该可以,如果你弄明白为什么unicode会引起NameError的话。 还可以用try:

#... now you have k, row[k]
  try:
    k += str(row[k])
  except UnicodeEncodeError:
    k += row[k]
中文注释的问题,#5楼就提到了。
感谢panghuhu250的耐心教导!!! 终于成了! 想不到unicode编码的字符串还不可以用str(unicodeString);
Jave.Lin 2013-08-06
  • 打赏
  • 举报
回复
引用 14 楼 maniachhz 的回复:
还有,types模块使用语法是: type(row(k)) is types.StringType
谢谢指导
Jave.Lin 2013-08-06
  • 打赏
  • 举报
回复
引用 16 楼 panghuhu250 的回复:
如果已经是gbk编码了,为什么要解码,再encode('gbk')?直接用就行了。
因为一直报,ascii转码不成,str(row[k])的前3个字节(position 0-2)转不成; 所以我认为是MySQLdb出来的字符编码为:ascii了; 但在连接时我就指定为:gbk了; 结果还是老报ascii的问题; 之后,你在5L说了:先把源来的编码(from coding)转成unicode,再encode自己想要的编码 因为decode,与encode这两个方法一般的对象是没有的(除非自己的类自己写的不算); decoder("from coding").encode("target coding"); 对了,经过上面的文字分析; str(row[k])一报报转ascii失败; 那说明str默认是转成:ascii码的? 那python有没有,将任意对象,转成指自己编码字符串的方法; 我现在知道:class 下都可以自己写个:__str__来给外部str(myClassInst)来调用; 但转出来的字符默认都是ascii; 有没有类似这样的方法,假设:str(obj, "charset")
panghuhu250 2013-08-06
  • 打赏
  • 举报
回复
引用 13 楼 linjf520 的回复:
conn = MySQLdb.connect(host='...', user='...', passwd='...', db='...', port=8001, charset='gbk') 后面的charset='gbk' 就是我想要的编码啊; 但不知道为神马,老是提示:ascii的问题;
如果已经是gbk编码了,为什么要解码,再encode('gbk')?直接用就行了。
maniachhz 2013-08-06
  • 打赏
  • 举报
回复
更正上面: row(k)应为row[k]
maniachhz 2013-08-06
  • 打赏
  • 举报
回复
str()好像转换不了多字节字符的,所以会出错. 使用row(k).decode('xxx').encode('xxx'),就转换成str 类型. 还有,types模块使用语法是: type(row(k)) is types.StringType
Jave.Lin 2013-08-06
  • 打赏
  • 举报
回复
引用 12 楼 panghuhu250 的回复:
引用
问题是这个"from coding"我不知道;
是你的程序设计的就是要处理未知编码的数据,还是数据库只有一个,但你不知道它用的编码?
conn = MySQLdb.connect(host='...', user='...', passwd='...', db='...', port=8001, charset='gbk') 后面的charset='gbk' 就是我想要的编码啊; 但不知道为神马,老是提示:ascii的问题;
panghuhu250 2013-08-06
  • 打赏
  • 举报
回复
引用 17 楼 linjf520 的回复:
因为一直报,ascii转码不成,str(row[k])的前3个字节(position 0-2)转不成; 所以我认为是MySQLdb出来的字符编码为:ascii了; 但在连接时我就指定为:gbk了; 结果还是老报ascii的问题; 之后,你在5L说了:先把源来的编码(from coding)转成unicode,再encode自己想要的编码 因为decode,与encode这两个方法一般的对象是没有的(除非自己的类自己写的不算); decoder("from coding").encode("target coding"); 对了,经过上面的文字分析; str(row[k])一报报转ascii失败; 那说明str默认是转成:ascii码的? 那python有没有,将任意对象,转成指自己编码字符串的方法; 我现在知道:class 下都可以自己写个:__str__来给外部str(myClassInst)来调用; 但转出来的字符默认都是ascii; 有没有类似这样的方法,假设:str(obj, "charset")
把obj转变为str,与把str编码是两件事,为什么要把他们合在一起? obj ----> str(obj) ----> encode('xxx') object unicode desired encode 这样,obj只要知道怎么用unicode表示自己。 你的例子中,为什么不直接:
print k + "=" row[k]
或者转为unicode:
print k + "=" row[k].decode('gbk')
panghuhu250 2013-08-05
  • 打赏
  • 举报
回复
引用
问题是这个"from coding"我不知道;
是你的程序设计的就是要处理未知编码的数据,还是数据库只有一个,但你不知道它用的编码? 如果你要处理的数据有各种编码的,最可靠的办法是加一个参数(函数参数或设置参数)来指定编码。有时同一个byte串可以用多种编码解码,只有人才能知道那个解码有意义。例如(这个例子大概机器也可以通过自然语言处理知道'汉字'是有意义的解码,另一个不是,但这只是我随便试的一个例子):

In [78]: a= u'汉字'.encode('utf-8')

In [79]: len(a)
Out[79]: 6

In [80]: a.decode('gbk')
Out[80]: u'\u59f9\u590a\u74e7'

In [81]: print a.decode('gbk')
姹夊瓧
如果是第二种情况,设法找出你的数据库用的编码。
加载更多回复(11)

37,719

社区成员

发帖
与我相关
我的任务
社区描述
JavaScript,VBScript,AngleScript,ActionScript,Shell,Perl,Ruby,Lua,Tcl,Scala,MaxScript 等脚本语言交流。
社区管理员
  • 脚本语言(Perl/Python)社区
  • IT.BOB
加入社区
  • 近7日
  • 近30日
  • 至今

试试用AI创作助手写篇文章吧