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

Answer from Martijn Pieters on Stack Overflow
🌐
W3Schools
w3schools.com › python › ref_string_encode.asp
Python String encode() Method
Python Examples Python Compiler ... The encode() method encodes the string, using the specified encoding. If no encoding is specified, UTF-8 will be used....
🌐
Python documentation
docs.python.org › 3 › howto › unicode.html
Unicode HOWTO — Python 3.14.7 documentation
You could then edit Python source ... characters used at runtime. Python supports writing source code in UTF-8 by default, but you can use almost any encoding if you declare the encoding being used....
Discussions

unicode - python encoding utf-8 - Stack Overflow
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 More on stackoverflow.com
🌐 stackoverflow.com
Working with UTF-8 encoding in Python source - Stack Overflow
You need not use unicode(), simply write string in UTF-8 encoding. 2011-06-09T08:03:22.567Z+00:00 ... In Python versions older than 3, you also need to prefix unicode string literals with "u": some_string = u'idzie wąż wąską dróżką'. 2011-06-09T08:06:28.08Z+00:00 More on stackoverflow.com
🌐 stackoverflow.com
Unicode (UTF-8) reading and writing to files in Python - Stack Overflow
Rather than mess with .encode and .decode, specify the encoding when opening the file. The io module, added in Python 2.6, provides an io.open function, which allows specifying the file's encoding. Supposing the file is encoded in UTF-8, we can use: More on stackoverflow.com
🌐 stackoverflow.com
UTF-8 encoding

Must not the utf-8 encoding, in this case, be on the first line and the comment on the second line?

You can actually put both on the first line. The python encoding behavior is defined in PEP0263 which states that you can put a "magic" encoding comment in line 1 or line 2. What counts as an encoding specification is very loose, technically anything that matches the regular expression coding[:=]\s*([-\w.]+). So all of the following comments on line 1 (or 2) will change the default encoding of Python 2 to utf-8:

# -*- coding: utf-8 -*-
# !?! coding: utf-8 ?!?
# coding=utf-8
#### the quick brown fox jumped coding=utf-8 over the lazy dog

You can mix in non-ascii characters on that same line provided the interpreter gets a match for the coding expression that is valid for those characters:

# åäö coding=utf-8 åäö

But if you have non-ascii characters on line 1, you can't leave the encoding specification until line 2. The following

# åäö 
# coding=utf-8 åäö

Results in:

SyntaxError: Non-ASCII character '\xc3'

Of course, as others point out, this is completely trivial in python 3 where utf-8 is the default encoding. You just put those characters in a comment in the first line.

More on reddit.com
🌐 r/learnpython
6
6
October 31, 2015
🌐
Real Python
realpython.com › python-encodings-guide
Unicode & Character Encodings in Python: A Painless Guide – Real Python
May 20, 2019 - Python 3 source code is assumed to be UTF-8 by default. This means that you don’t need # -*- coding: UTF-8 -*- at the top of .py files in Python 3. All text (str) is Unicode by default. Encoded Unicode text is represented as binary data (bytes).
Top answer
1 of 2
65

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

2 of 2
2

Unfortunately, the string.encode() method is not always reliable. Check out this thread for more information: What is the fool proof way to convert some string (utf-8 or else) to a simple ASCII string in python

🌐
Honeybadger
honeybadger.io › blog › python-character-encoding
Python developer's guide to character encoding - Honeybadger Developer Blog
March 6, 2023 - In Python 3, every string uses the Unicode format to represent characters by default. It implies that each text has a specific code point that displays the characters using UTF-8 as the default encoding.
🌐
Python Basics
python-basics-tutorial.readthedocs.io › en › latest › types › strings › encodings.html
Unicode and character encodings - Python Basics
UTF-8 is an encoding scheme for representing Unicode characters as binary data with one or more bytes per character. Added in version 3.15: Python 3.15 uses UTF-8 as the default encoding, regardless of the system environment.
🌐
Programiz
programiz.com › python-programming › methods › string › encode
Python String encode()
# print string print('The string is:', string) # default encoding to utf-8 · string_utf = string.encode() # print result print('The encoded version is:', string_utf) ... The string is: pythön! The encoded version (with ignore) is: b'pythn!' The encoded version (with replace) is: b'pyth?n!' Note: Try different encoding and error parameters as well. Since Python 3.0, strings are stored as Unicode, i.e.
Find elsewhere
🌐
LabEx
labex.io › tutorials › python-how-to-use-python-utf8-encoding-451217
How to use Python UTF8 encoding | LabEx
Encoding and decoding are fundamental processes for converting text between different representations in Python. ## String to bytes encoding text = "Hello, 世界!" encoded_text = text.encode('utf-8') print(encoded_text) ## Converts string to UTF-8 bytes ## Bytes to string decoding decoded_text = encoded_text.decode('utf-8') print(decoded_text) ## Converts bytes back to string
🌐
Real Python
realpython.com › lessons › encoding-utf8
Encoding UTF-8 (Video) – Real Python
The purpose of this lesson is to fulfill your curiosity about UTF-8. Generally, you don’t need to understand the inner workings of this to be able to successfully use UTF-8 and Unicode in Python. 00:48 Now that you’re familiar with hex, I’ve rewritten the method that shows the code points, this time showing it in hex code points. I’ve put this inside of a file called points.py. 01:01 I can import this function, and then write a string… and look at the encoding.
Published: June 30, 2020
🌐
GeeksforGeeks
geeksforgeeks.org › python › convert-a-string-to-utf-8-in-python
Convert a String to Utf-8 in Python - GeeksforGeeks
July 23, 2025 - Converting a string to UTF-8 in Python is a simple task with multiple methods at your disposal. Whether you choose the encode method, the bytes constructor, or the str.encode method, the key is to specify the UTF-8 encoding.
🌐
MojoAuth
mojoauth.com › character-encoding-decoding › utf-8-encoding--python
UTF-8 Encoding : Python | Encoding Solutions Across Programming Languages
When encoded, the UTF-8 representation is a bytes sequence that can be stored or transmitted efficiently. Decoding is the reverse process of encoding, and it is equally easy in Python.
🌐
Python
peps.python.org › pep-0263
PEP 263 – Defining Python Source Code Encodings | peps.python.org
There must not be any Python statement on the line that contains the encoding declaration. If the first line matches the second line is ignored. To aid with platforms such as Windows, which add Unicode BOM marks to the beginning of Unicode files, the UTF-8 signature \xef\xbb\xbf will be interpreted as ‘utf-8’ encoding as well (even if no magic encoding comment is given).
🌐
Python
docs.python.org › 2 › howto › unicode.html
Unicode HOWTO — Python 2.7.18 documentation
The function’s parameters are ... to update the file. buffering is similarly parallel to the standard function’s parameter. encoding is a string giving the encoding to use; if it’s left as None, a regular Python file object that accepts 8-bit strings is retur...
🌐
Python Basics
python-basics-tutorial.readthedocs.io › en › 24.3.0 › appendix › encodings.html
Unicode and character encodings - Python Basics 24.3.0
8-bit · While Unicode is an abstract encoding standard, UTF-8 is a concrete encoding scheme. The Unicode standard is a mapping of characters to code points and defines several different encodings from a single character set.
🌐
SSOJet
ssojet.com › character-encoding-decoding › utf-8-in-python
UTF-8 in Python | Encoding Standards for Programming Languages
To avoid errors, consistently encode ... byte data. When working with text files in Python, explicitly specifying the encoding='utf-8' parameter in the open() function is crucial for accurate character handling....
🌐
Medium
lynn-kwong.medium.com › understand-the-encoding-decoding-of-python-strings-unicode-utf-8-f6f97a909ee0
Understand the encoding/decoding of Python strings (Unicode/UTF-8) | by Lynn G. Kwong | Medium
August 25, 2023 - String is a common data type in Python and is used by us every day. In this article, the basics of the encoding/decoding of strings will be introduced which can clear your confusion in this field.
🌐
Evanjones
evanjones.ca › python-utf8.html
How to Use UTF-8 with Python (evanjones.ca)
You can do this in one of two ways. First, you can place a UTF-8 byte-order marker at the beginning of your file, if your editor supports it. Secondly, you can place the following special comment in the first or second lines of your script: ... Any ASCII-compatible encoding is permitted.
Top answer
1 of 14
914

Rather than mess with .encode and .decode, specify the encoding when opening the file. The io module, added in Python 2.6, provides an io.open function, which allows specifying the file's encoding.

Supposing the file is encoded in UTF-8, we can use:

>>> import io
>>> f = io.open("test", mode="r", encoding="utf-8")

Then f.read returns a decoded Unicode object:

>>> f.read()
u'Capit\xe1l\n\n'

In 3.x, the io.open function is an alias for the built-in open function, which supports the encoding argument (it does not in 2.x).

We can also use open from the codecs standard library module:

>>> import codecs
>>> f = codecs.open("test", "r", "utf-8")
>>> f.read()
u'Capit\xe1l\n\n'

Note, however, that this can cause problems when mixing read() and readline().

2 of 14
126

In the notation u'Capit\xe1n\n' (should be just 'Capit\xe1n\n' in 3.x, and must be in 3.0 and 3.1), the \xe1 represents just one character. \x is an escape sequence, indicating that e1 is in hexadecimal.

Writing Capit\xc3\xa1n into the file in a text editor means that it actually contains \xc3\xa1. Those are 8 bytes and the code reads them all. We can see this by displaying the result:

# Python 3.x - reading the file as bytes rather than text,
# to ensure we see the raw data
>>> open('f2', 'rb').read()
b'Capit\\xc3\\xa1n\n'

# Python 2.x
>>> open('f2').read()
'Capit\\xc3\\xa1n\n'

Instead, just input characters like á in the editor, which should then handle the conversion to UTF-8 and save it.

In 2.x, a string that actually contains these backslash-escape sequences can be decoded using the string_escape codec:

# Python 2.x
>>> print 'Capit\\xc3\\xa1n\n'.decode('string_escape')
Capitán

The result is a str that is encoded in UTF-8 where the accented character is represented by the two bytes that were written \\xc3\\xa1 in the original string. To get a unicode result, decode again with UTF-8.

In 3.x, the string_escape codec is replaced with unicode_escape, and it is strictly enforced that we can only encode from a str to bytes, and decode from bytes to str. unicode_escape needs to start with a bytes in order to process the escape sequences (the other way around, it adds them); and then it will treat the resulting \xc3 and \xa1 as character escapes rather than byte escapes. As a result, we have to do a bit more work:

# Python 3.x
>>> 'Capit\\xc3\\xa1n\n'.encode('ascii').decode('unicode_escape').encode('latin-1').decode('utf-8')
'Capitán\n'