Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python encoding utf-8

I am doing some scripts in python. I create a string that I save in a file. This string got lot of data, coming from the arborescence and filenames of a directory. According to convmv, all my arborescence is in UTF-8.

I want to keep everything in UTF-8 because I will save it in MySQL after. For now, in MySQL, which is in UTF-8, I got some problem with some characters (like é or è - I'am French).

I want that python always use string as UTF-8. I read some informations on the internet and i did like this.

My script begin with this :

 #!/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! 

And when I execute, here is the answer : UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 2171: ordinal not in range(128)

Edit: I see, in my file, the accent are nicely written. After creating this file, I read it and I write it into MySQL. But I dont understand why, but I got problem with encoding. My MySQL database is in utf8, or seems to be SQL query SHOW variables LIKE 'char%' returns me only utf8 or binary.

My function looks like this :

#!/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') 

And artiste who are nicely displayed in the file writes bad into the BDD. What is the problem ?

like image 880
vekah Avatar asked Feb 26 '13 15:02

vekah


People also ask

How do you encode and decode UTF-8 in Python?

decode() to decode a UTF-8-encoded byte string. Call bytes. decode(encoding) with encoding as "utf8" to decode a UTF-8-encoded byte string bytes .

What is decode (' UTF-8 ') in Python?

Python Python Decoding Python UTF-8. Created: January-06, 2022. Encoding refers to encoding a string using an encoding scheme such as UTF-8 . Decoding refers to converting an encoded string from one encoding to another encoding scheme.

What is encoding =' UTF-8?

UTF-8 is an encoding system for Unicode. It can translate any Unicode character to a matching unique binary string, and can also translate the binary string back to a Unicode character. This is the meaning of “UTF”, or “Unicode Transformation Format.”


1 Answers

You don't need to encode data that is already encoded. When you try to do that, Python will first try to decode it to unicode before it can encode it back to UTF-8. That is what is failing here:

>>> 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) 

Just write your data directly to the file, there is no need to encode already-encoded data.

If you instead build up unicode values instead, you would indeed have to encode those to be writable to a file. You'd want to use codecs.open() instead, which returns a file object that will encode unicode values to UTF-8 for you.

You also really don't want to write out the UTF-8 BOM, unless you have to support Microsoft tools that cannot read UTF-8 otherwise (such as MS Notepad).

For your MySQL insert problem, you need to do two things:

  • Add charset='utf8' to your MySQLdb.connect() call.

  • Use unicode objects, not str objects when querying or inserting, but use sql parameters so the MySQL connector can do the right thing for you:

    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'/')) 

It may actually work better if you used codecs.open() to decode the contents automatically instead:

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 

You may want to brush up on Unicode and UTF-8 and encodings. I can recommend the following articles:

  • The Python Unicode HOWTO

  • Pragmatic Unicode by Ned Batchelder

  • The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!) by Joel Spolsky

like image 79
Martijn Pieters Avatar answered Sep 30 '22 03:09

Martijn Pieters