如何在setup.py中指定多个作者/电子邮件

我们写了一个小封装到twitter应用程序,并将这些信息发布到http://pypi.python.org 。 但是setup.py只包含一个用于指定作者的email / name的字段。 我如何指定多个贡献者/电子邮件列表,以下字段,因为我们希望这个软件包被列在我们的名字下,与http://rubygems.org上显示的很类似。

author='foo', author_email='foo.bar@gmail.com', 

据我所知, setuptools不支持使用string列表来指定多个作者。 您最好的select是将作者列在一个string中:

 author='Foo Bar, Spam Eggs', author_email='foobar@baz.com, spameggs@joe.org', 

我不确定PyPI是否validation了author_email字段,因此您可能会遇到麻烦。 无论如何,我build议您将这些限制在一个作者身上,并在文档或说明中提及所有贡献者。

[编辑]有些来源:

实际上,这已经被注册为一个错误 ,但似乎对多个作者的支持没有实现。 这是一个替代解决scheme。 这里有一个关于如何为多个作者提供联系电子邮件的想法。

我只是捎带@ modocache的答案,以防你想要一些细节。

在整个这个答案中,我将引用一个python3.6版本的FOO-PYTHON-ENV\Lib\distutils\dist.py文件

重申一下,您不能在author字段中使用列表。 原因如下:

破坏者:属于DistributionMetadata类的两个方法是原因 –

 def _read_field(name): value = msg[name] if value == 'UNKNOWN': return None return value def _read_list(name): values = msg.get_all(name, None) if values == []: return None return values 

如果您尝试在author字段中粘贴一个列表,则会出现以下错误:

 class DistributionMetadata: #*...(REDACTED)...*# def read_pkg_file(self, file): """Reads the metadata values from a file object.""" #*...(REDACTED)...*# # #################################### # Note the usage of _read_field() here # #################################### self.name = _read_field('name') self.version = _read_field('version') self.description = _read_field('summary') # we are filling author only. self.author = _read_field('author') self.maintainer = None self.author_email = _read_field('author-email') self.maintainer_email = None self.url = _read_field('home-page') self.license = _read_field('license') #*...(REDACTED)...*# # ################################### # Note the usage of _read_list() here # ################################### self.platforms = _read_list('platform') self.classifiers = _read_list('classifier') #*...(REDACTED)...*# 

这是整个事情:

 class DistributionMetadata: """Dummy class to hold the distribution meta-data: name, version, author, and so forth. """ _METHOD_BASENAMES = ("name", "version", "author", "author_email", "maintainer", "maintainer_email", "url", "license", "description", "long_description", "keywords", "platforms", "fullname", "contact", "contact_email", "classifiers", "download_url", # PEP 314 "provides", "requires", "obsoletes", ) def __init__(self, path=None): if path is not None: self.read_pkg_file(open(path)) else: self.name = None self.version = None self.author = None self.author_email = None self.maintainer = None self.maintainer_email = None self.url = None self.license = None self.description = None self.long_description = None self.keywords = None self.platforms = None self.classifiers = None self.download_url = None # PEP 314 self.provides = None self.requires = None self.obsoletes = None def read_pkg_file(self, file): """Reads the metadata values from a file object.""" msg = message_from_file(file) def _read_field(name): value = msg[name] if value == 'UNKNOWN': return None return value def _read_list(name): values = msg.get_all(name, None) if values == []: return None return values metadata_version = msg['metadata-version'] self.name = _read_field('name') self.version = _read_field('version') self.description = _read_field('summary') # we are filling author only. self.author = _read_field('author') self.maintainer = None self.author_email = _read_field('author-email') self.maintainer_email = None self.url = _read_field('home-page') self.license = _read_field('license') if 'download-url' in msg: self.download_url = _read_field('download-url') else: self.download_url = None self.long_description = _read_field('description') self.description = _read_field('summary') if 'keywords' in msg: self.keywords = _read_field('keywords').split(',') self.platforms = _read_list('platform') self.classifiers = _read_list('classifier') # PEP 314 - these fields only exist in 1.1 if metadata_version == '1.1': self.requires = _read_list('requires') self.provides = _read_list('provides') self.obsoletes = _read_list('obsoletes') else: self.requires = None self.provides = None self.obsoletes = None