Как правильно использовать метаданные Unicode в setup.py ?
-
18-09-2019 - |
Вопрос
Я писал a 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", что означает, что уродливые хаки, которые заглядывают в 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("..."),
...)
Разве нет лучшего способа?
Решение
По-видимому, это ошибка distutils, которая была исправлена в python 2.6: http://mail.python.org/pipermail/distutils-sig/2009-September/013275.html
Тарек предлагает исправить post_to_server.Исправление должно предварительно обработать все значения в аргументе "data" и преобразовать их в юникод, а затем вызвать исходный метод.Видишь http://mail.python.org/pipermail/distutils-sig/2009-September/013277.html
Другие советы
#!/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;загрузка, кажется, работает нормально (хотя я отменяю фактическую загрузку), и register запрашивает у меня мое имя пользователя, которого у меня нет.Но обратная трассировка в вашем комментарии полезна - это автоматическое преобразование в unicode
в register
команда, которая вызывает проблему.
Видишь иллюзорное кодирование setdefaultencoding для получения дополнительной информации об этом - в принципе, вы хотите, чтобы кодировка по умолчанию в Python позволяла преобразовывать вашу закодированную строку обратно в unicode, но это сложно настроить.В данном случае, я думаю, это стоит затраченных усилий:
import sys
reload(sys).setdefaultencoding("UTF-8")
Или даже, чтобы быть корректным, вы можете получить его из locale
- там есть код, закомментированный в /usr/lib/python2.6/site.py
что вы можете найти, что делает это, но я пока оставлю это обсуждение.
Вам нужно изменить свое длинное описание в юникоде u"bläh bläh bläh"
к обычной строке "bläh bläh bläh"
и добавьте заголовок encoding в качестве второй строки вашего файла:
#!/usr/bin/env python
# encoding: utf-8
...
...
Очевидно, что вам также необходимо сохранить файл в кодировке UTF-8.