2009-07-21 7 views
8

je rédigeais un setup.py pour un paquet Python en utilisant setuptools et voulaient inclure un caractère non-ASCII dans le champ long_description:Quelle est la bonne façon d'utiliser les métadonnées Unicode dans setup.py?

#!/usr/bin/env python 
from setuptools import setup 
setup(... 
     long_description=u"...", # in real code this value is read from a text file 
     ...) 

Malheureusement, le passage d'un objet unicode à la configuration() brise l'une des après deux commandes avec un UnicodeEncodeError

 
python setup.py --long-description | rst2html 
python setup.py upload 

Si j'utilise une chaîne UTF-8 premières pour le champ long_description, puis les pauses de commande suivantes avec un UnicodeDecodeError:

 
python setup.py register 

Je publie généralement un logiciel en exécutant 'python setup.py sdist register upload', ce qui signifie que les hacks vilains qui regardent sys.argv et passent le bon type d'objet sont à droite.

En fin de compte, j'ai abandonné et mis en œuvre un autre bidouille horrible:

class UltraMagicString(object): 
    # Catch-22: 
    # - if I return Unicode, python setup.py --long-description as well 
    # as python setup.py upload fail with a UnicodeEncodeError 
    # - if I return UTF-8 string, python setup.py sdist register 
    # fails with an UnicodeDecodeError 

    def __init__(self, value): 
     self.value = value 

    def __str__(self): 
     return self.value 

    def __unicode__(self): 
     return self.value.decode('UTF-8') 

    def __add__(self, other): 
     return UltraMagicString(self.value + str(other)) 

    def split(self, *args, **kw): 
     return self.value.split(*args, **kw) 

... 

setup(... 
     long_description=UltraMagicString("..."), 
     ...) 

N'y at-il une meilleure façon?

Répondre

3
#!/usr/bin/env python 
# -*- coding: utf-8 -*- 

from setuptools import setup 
setup(name="fudz", 
     description="fudzily", 
     version="0.1", 
     long_description=u"bläh bläh".encode("UTF-8"), # in real code this value is read from a text file 
     py_modules=["fudz"], 
     author="David Fraser", 
     author_email="[email protected]", 
     url="http://en.wikipedia.org/wiki/Fudz", 
    ) 

Je teste avec le code ci-dessus - il n'y a pas d'erreur de --long-description, seulement de rst2html; Le téléchargement semble fonctionner correctement (bien que j'annule le téléchargement) et l'enregistrement me demande mon nom d'utilisateur que je n'ai pas. Mais la traceback dans votre commentaire est utile - c'est la conversion automatique à unicode dans la commande register qui provoque le problème. Pour plus d'informations à ce sujet, voir the illusive setdefaultencoding. En gros, vous voulez que l'encodage par défaut en Python puisse convertir votre chaîne encodée en unicode, mais c'est difficile à configurer. Dans ce cas, je pense qu'il vaut la peine:

import sys 
reload(sys).setdefaultencoding("UTF-8") 

Ou même être correct, vous pouvez l'obtenir à partir du locale - il le code est commenté dans /usr/lib/python2.6/site.py que vous pouvez trouver qui fait cela, mais je vais laisser cette discussion pour l'instant.

+0

Je ne suis pas sûr de pouvoir coller la trace complète dans un commentaire ici; la traceback se termine dans /usr/lib/python2.6/distutils/command/register.py ligne 264 (dans post_to_server) où il essaie de le faire: value = unicode (value) .encode ("utf-8"). Comme vous pouvez le voir, j'utilise Python 2.6; une version plus récente de distutils devrait être vraiment saignante. –

+0

Vous remarquerez que la reproduction nécessite que vous ayez au moins un caractère non-ASCII dans le champ. –

+0

Je peux reproduire la configuration 'python.py register 'erreur avec les trois versions de Python que j'ai ici: 2.4, 2.5 et 2.6. –

1

Vous devez changer votre unicode description longue u"bläh bläh bläh" à une chaîne normale "bläh bläh bläh" et ajouter un en-tête de codage de la deuxième ligne de votre fichier:

#!/usr/bin/env python 
# encoding: utf-8 
... 
... 

De toute évidence, vous devez enregistrer le fichier avec UTF-8 encodage, aussi.

+0

"Si j'utilise une chaîne UTF-8 brute pour le champ long_description, alors la commande suivante casse avec un UnicodeDecodeError: python setup.py enregistre" –

+0

_Not_ une chaîne brute (r "bläh bläh"), juste une chaîne normale dans la source. Cela a fonctionné pour moi en tapant simplement le code. Assurez-vous de sauvegarder le fichier avec l'encodage UTF-8. Vous avez dit que vous chargiez la vraie description longue depuis un fichier texte. Il est possible que vous ne décodiez pas correctement le texte lorsque vous le lisez dans le fichier. Assurez-vous de décoder le texte avec l'encodage correct pour le fichier texte. – wbg

+0

J'ai des problèmes similaires à Marius. J'ai des trémas dans un CHANGES.txt que j'utilise pour ma longue description. codecs.open (..., encoding = ...), toutes les bonnes choses. Mais à la fin, "setup.py --long-description" fait un "print" et "setup.py upload" fait un "unicode()". Et unicode d'une chaîne encodée par utf8 échoue et l'impression d'une chaîne unicode échoue. RAARGH. Marius: votre bidouille sale fonctionne comme un charme. –

Questions connexes