Il y a un bogue en python 2.x qui n'est fixe que python 3.x. En fait, ce bogue se trouve même dans l'iconv d'OS X (mais pas dans la glibc).
Voici ce qui se passe :
Python 2.x ne reconnaît pas les paires de substitution UTF8 [1] comme étant invalides (ce qui correspond à votre séquence de caractères)
Cela devrait être tout ce qui est nécessaire :
foo.decode('utf8').encode('utf8')
Mais grâce à ce bogue qu'ils ne corrigent pas, il n'attrape pas les paires de substitution.
Essayez ceci en python 2.x puis en 3.x :
b'\xed\xbd\xbf'.decode('utf8')
Il lancera une erreur (correctement) dans ce dernier. Ils ne le corrigent pas non plus dans la branche 2.x. Voir [2] et [3] pour plus d'informations
[1] https://www.rfc-editor.org/rfc/ rfc3629#section-4
[2] http://bugs.python.org/issue9133
[3] http://bugs.python.org/issue8271#msg102209