如何在setup.py中正确使用Unicode元数据?

10 投票
3 回答
2716 浏览
提问于 2025-04-15 13:04

我在用setuptools写一个Python包的setup.py文件时,想在long_description字段里加一个非ASCII字符。

#!/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

如果我在long_description字段里用一个原始的UTF-8字符串,那么下面的命令就会出错,出现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 个回答

1

你需要把你的unicode长描述 u"bläh bläh bläh" 改成普通字符串 "bläh bläh bläh",并在文件的第二行添加一个编码头:

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

显然,你还需要把文件保存为UTF-8编码格式。

4
#!/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的过程。

想了解更多信息,可以看看这个关于设置默认编码的博客——简单来说,你希望Python的默认编码能够把你的编码字符串转换回unicode,但设置这个有点麻烦。在这种情况下,我觉得值得花点时间去解决这个问题:

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

或者更准确地说,你可以从locale中获取这个编码——在/usr/lib/python2.6/site.py里有一段注释掉的代码可以做到这一点,但我暂时不想讨论这个。

6

这显然是一个在python 2.6中修复的distutils错误:http://mail.python.org/pipermail/distutils-sig/2009-September/013275.html

Tarek建议对post_to_server进行修补。这个修补应该先处理“data”参数中的所有值,把它们转换成unicode格式,然后再调用原来的方法。具体可以参考http://mail.python.org/pipermail/distutils-sig/2009-September/013277.html

撰写回答