Как правильно использовать метаданные Юникода в setup.py? - PullRequest
9 голосов
/ 22 июля 2009

Я писал setup.py для пакета Python, используя setuptools, и хотел включить не-ASCII-символ в поле long_description:

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

К сожалению, передача объекта Unicode в setup () прерывает любую из следующих двух команд с помощью UnicodeEncodeError

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

Если я использую необработанную строку UTF-8 для поля long_description, то следующая команда разрывается с UnicodeDecodeError:

python setup.py register

Я обычно выпускаю программное обеспечение, запуская 'python setup.py sdist register upload', что означает, что уродливые хаки, которые смотрят в sys.argv и передают нужный тип объекта, прямо сейчас.

В конце концов я сдался и реализовал другой уродливый хак:

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("..."),
      ...)

Разве нет лучшего способа?

Ответы [ 3 ]

5 голосов
/ 17 сентября 2009

Это, очевидно, ошибка distutils, исправленная в python 2.6: http://mail.python.org/pipermail/distutils-sig/2009-September/013275.html

Тарек предлагает патч post_to_server. Патч должен предварительно обработать все значения в «data» аргумент и превратить их в Unicode, а затем вызвать оригинальный метод. Смотри http://mail.python.org/pipermail/distutils-sig/2009-September/013277.html

3 голосов
/ 24 июля 2009
#!/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="davidf@sjsoft.com",
      url="http://en.wikipedia.org/wiki/Fudz",
      )

Я тестирую с помощью приведенного выше кода - нет ошибки из --long-description, только из rst2html; загрузка, кажется, работает нормально (хотя я фактически отменяю загрузку) и регистрирует запрос моего имени пользователя, которого у меня нет. Но обратная связь в вашем комментарии полезна - проблема заключается в автоматическом преобразовании в unicode в команде register.

См. Призрачное setdefaultencoding для получения дополнительной информации об этом - в основном вы хотите, чтобы кодировка по умолчанию в Python могла преобразовывать вашу закодированную строку обратно в Unicode, но это сложно настроить. В этом случае я думаю, что это стоит усилий:

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

Или, если быть точным, вы можете получить его из locale - есть код, закомментированный в /usr/lib/python2.6/site.py, который вы можете найти, который делает это, но я пока оставлю это обсуждение.

1 голос
/ 25 июля 2009

Вам нужно изменить длинное описание Юникода u"bläh bläh bläh" на обычную строку "bläh bläh bläh" и добавить заголовок кодировки в качестве второй строки вашего файла:

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

Очевидно, что вам также нужно сохранить файл в кодировке UTF-8.

...