解决Python2.7的UnicodeEncodeError: 'ascii' codec can't encode异常错误
提醒:本页面将不再更新、维护或者支持,文章、评论所叙述内容存在时效性,涉及技术细节或者软件使用方面不保证能够完全有效可操作,请谨慎参考!
今天准备将某SQLite数据库的内容导出到文本文档(*.txt)中,设计的Python程序如下:
# -*- coding: UTF-8 -*-
import sqlite3
def gsel(cur):
cur.execute("SELECT * FROM collection")
def main():
conn = sqlite3.connect("build.db3")
cur = conn.cursor()
gsel(cur)
# conn.commit()
rs = cur.fetchall()
fp = open("output.txt", "w")
for row in rs:
fp.write(row[1]) # 读取并写入第2列数据
if __name__ == '__main__':
main()
代码上面应该没有什么问题,Python使用的是版本2.7,但是在运行的时候出现了异常错误 UnicodeEncodeError :
Traceback (most recent call last): File "makedb.py", line 33, in <module> main() File "makedb.py", line 30, in main fp.write(row[1]) UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-78: ordinal not in range(128)
本来以为数据读取错误,我特将fp.write改成print,结果数据全部读取并显示在命令控制台上了,证明代码是没有问题的,仔细看了下异常信息,貌似是因为编码问题:Unicode编码与ASCII编码的不兼容,其实这个Python脚本文件是由utf-8编码的,同时SQlite3数据库存取的也是UTF-8格式,Python默认环境编码通过下面的方法可以获取:
import sys
print sys.getdefaultencoding()
# 'ascii'
基本上是ascii编码方式,由此Python自然调用ascii编码解码程序去处理字符流,当字符流不属于ascii范围内,就会抛出异常(ordinal not in range(128))。
解决的方案很简单,修改默认的编码模式,很多朋友会想到setdefaultencoding,是的,我们可以通过 sys.setdefaultencoding('utf-8') 来将当前的字符处理模式修改为utf-8编码模式,值得注意的是,如果单纯这么调用的话,Python会抛出一个AttributeError异常:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'setdefaultencoding'
竟然说sys没有setdefaultencoding的方法,其实sys是有这个方法的,但是要请出她老人家需要调用一次 reload(sys) ,很奇怪,是么?如果有谁知道原因的话,还望不吝赐教。
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
好了,通过上面短短的三行,我们算是很好的解决了这个问题了,同样的方式也可以应用到 UnicodeDecodeError 上。当然这个技巧来自于网络,我还找到其他特别的办法,但是感觉还是这个比较靠谱,有童鞋说:我们将Python 2.x系列升级到Python 3.x系列就可以了,小小的问题犯不着升级吧,毕竟2到3还是要有个过渡的。
最后,我将文章一开始的代码更改如下:
# -*- coding: UTF-8 -*-
import sys # 1
import sqlite3
def gsel(cur):
cur.execute("SELECT * FROM collection")
def main():
reload(sys) # 2
sys.setdefaultencoding('utf-8') # 3
conn = sqlite3.connect("build.db3")
cur = conn.cursor()
gsel(cur)
# conn.commit()
rs = cur.fetchall()
fp = open("output.txt", "w")
for row in rs:
fp.write(row[1])
if __name__ == '__main__':
main()
看起来,你这里的问题,其实是: 把文件内容,写入到文件中时,出错了。 而出错的原因其实是,python系统,在使用默认的编码类型,此处的ascii,去将对应的内容,写入到文件中。 但是由于其中一些内容,ascii编码不支持,所以报错。 所以,更好的办法是,在输出的时候,对文件制定特定的UTF-8编码即可。 而无需改动默认编码。 具体做法是: 不使用open打开文件,而使用codecs: fp = codecs.open('output.txt', 'a+', 'utf-8');; fp.write(row[1]); fp.close();
感谢你提供的方法,学习了:-)
感谢~学习了!
正解
谢谢大神
3Q,终于解决了!
楼主我也遇到了类似的问题,但是我加了这段语句之后程序就不往下运行了: import sys def main(): print("1") reload(sys) sys.setdefaultencoding( "utf-8" ) print("2") if __name__ == '__main__': main() 只能输出1,不会输出2. 请问这个问题怎么解决?
我这个是针对Python2系列的,看你的print的使用方法推断你应该使用的Python3吧,Python3通常不需要此类操作(即不需要
reload
和sys.setdefaultencoding
),直接在文件一开头(第一行)加上# -*- coding: UTF-8 -*-
然后把文件存为UTF-8编码即可。非常感谢。只有你是正确的
你好~ 我用的也是python2.7 但是sys里面没有setdefaultencoding函数呀~
你好~ 我知道为啥没有这个函数了。要reload一下,但是这段代码只在Python shell里面起作用,写在文件里面以后就一直运行不出来,就是运行到reload以后就一直没有进行下去,而是直接结束了~这点我很不明白~
请问你是怎么解决的呢?
好吧~我用另外一个方法解决了~谢谢你的分享。
那个,需要reload一次是因为python启动时会调用setdefaultencoding一次, 直接import sys不会对已经调用的函数载入, 只有reload一次才能重新载入这个函数... 大概是这样,我的描述可能有些不清晰...这个问题在 python学习手册(第四版) 里有写, 我找不到位置了, 八百页的书.
谢谢提示:-)
[…] 为了解决此问题解决Python2.7的UnicodeEncodeError: ‘ascii’ codec can’t encode异常错误 从而在代码中使用了reload(sys) 但在此句过后,print语句无法正常输出内容,有办法解决吗?>>> print 123123>>> print sys.getdefaultencoding()cp936>>> reload(sys)>>> print sys.getdefaultencoding()>>> print 123>>> —————————————————————————————————————————————————— ↓ 解决方案 ↓ […]
太好了,虽然有好多没看懂,不过还是解决了。谢谢大神
在python的Lib\site-packages文件夹下新建一个sitecustomize.py,内容为: # encoding=utf8 import sys reload(sys) sys.setdefaultencoding('utf8')
感谢你提供的方法:-)
如果是pyScripter编译python中提示的编码错误, 打开“运行”菜单栏,找到“Python引擎” 选择“内部”即可
[…] 解决Python2.7的UnicodeEncodeError: ‘ascii’ codec can’t encode异常错误 […]