我正在用python做一些脚本。我创建一个保存在文件中的字符串。这个字符串有很多数据,来自目录的树状结构和文件名。根据convmv的介绍,我所有的树状结构都是UTF-8。
我想将所有内容都保留在UTF-8中,因为之后我将其保存在MySQL中。现在,在UTF-8的MySQL中,我遇到了一些字符问题(例如é或è-我是法语)。
我希望python始终将字符串用作UTF-8。我在互联网上阅读了一些信息,我确实这样做。
我的脚本以此开头:
#!/usr/bin/python # -*- coding: utf-8 -*- def createIndex(): import codecs toUtf8=codecs.getencoder('UTF8') #lot of operations & building indexSTR the string who matter findex=open('config/index/music_vibration_'+date+'.index','a') findex.write(codecs.BOM_UTF8) findex.write(toUtf8(indexSTR)) #this bugs!
当我执行时,这是答案: UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 2171: ordinal not in range(128)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 2171: ordinal not in range(128)
编辑:我看到在我的文件中,口音写得很好。创建此文件后,我将其读取并将其写入MySQL。但是我不明白为什么,但是我在编码方面遇到了问题。我的MySQL数据库位于utf8中,或者似乎是SQL查询,SHOW variables LIKE 'char%'仅返回utf8或二进制。
SHOW variables LIKE 'char%'
我的功能看起来像这样:
#!/usr/bin/python # -*- coding: utf-8 -*- def saveIndex(index,date): import MySQLdb as mdb import codecs sql = mdb.connect('localhost','admin','*******','music_vibration') sql.charset="utf8" findex=open('config/index/'+index,'r') lines=findex.readlines() for line in lines: if line.find('#artiste') != -1: artiste=line.split('[:::]') artiste=artiste[1].replace('\n','') c=sql.cursor() c.execute('SELECT COUNT(id) AS nbr FROM artistes WHERE nom="'+artiste+'"') nbr=c.fetchone() if nbr[0]==0: c=sql.cursor() iArt+=1 c.execute('INSERT INTO artistes(nom,status,path) VALUES("'+artiste+'",99,"'+artiste+'/")'.encode('utf8')
很好地显示在文件中的Artiste会将错误写入BDD。问题是什么 ?
您不需要对 已经 编码的数据进行编码。当您尝试执行此操作时,Python会先尝试对其进行 解码 ,unicode然后再将其编码回UTF-8。这就是这里失败的原因:
unicode
>>> data = u'\u00c3' # Unicode data >>> data = data.encode('utf8') # encoded to UTF-8 >>> data '\xc3\x83' >>> data.encode('utf8') # Try to *re*-encode it Traceback (most recent call last): File "<stdin>", line 1, in <module> UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0: ordinal not in range(128)
只需直接写您的数据文件,也 没有 必要编码已编码的数据。
如果改为建立unicode值,则实际上必须将那些值编码为可写入文件。您想使用codecs.open()它,它返回一个文件对象,该文件对象将为您将Unicode值编码为UTF-8。
codecs.open()
您也 确实 不想写UTF-8 BOM, 除非 您 必须 支持否则无法读取UTF-8的Microsoft工具(例如MS Notepad)。
对于您的MySQL插入问题,您需要做两件事:
添加charset='utf8'到您的MySQLdb.connect()通话中。
charset='utf8'
MySQLdb.connect()
使用unicode对象,而不是str查询或插入对象,而是 使用sql参数, 以便MySQL连接器可以为您做正确的事情:
str
artiste = artiste.decode('utf8') # it is already UTF8, decode to unicode
c.execute(‘SELECT COUNT(id) AS nbr FROM artistes WHERE nom=%s’, (artiste,))
c.execute(‘INSERT INTO artistes(nom,status,path) VALUES(%s, 99, %s)’, (artiste, artiste + u’/’))
如果您codecs.open()改为自动解码内容,则实际上可能会更好:
import codecs sql = mdb.connect('localhost','admin','ugo&(-@F','music_vibration', charset='utf8') with codecs.open('config/index/'+index, 'r', 'utf8') as findex: for line in findex: if u'#artiste' not in line: continue artiste=line.split(u'[:::]')[1].strip() cursor = sql.cursor() cursor.execute('SELECT COUNT(id) AS nbr FROM artistes WHERE nom=%s', (artiste,)) if not cursor.fetchone()[0]: cursor = sql.cursor() cursor.execute('INSERT INTO artistes(nom,status,path) VALUES(%s, 99, %s)', (artiste, artiste + u'/')) artists_inserted += 1
您可能需要复习Unicode和UTF-8和编码。我可以推荐以下文章:
在Python的Unicode指南
Ned Batchelder的实用Unicode
每个软件开发人员绝对,肯定必须绝对了解Unicode和字符集(无借口!)作者:Joel Spolsky