如何编写 setup.py 来包含一个 Git 存储库作为依赖项

我正在尝试为我的软件包编写 setup.py。我的软件包需要指定另一个 Git 存储库的依赖项。

以下是我目前掌握的情况:

from setuptools import setup, find_packages


setup(
name='abc',
packages=find_packages(),
url='https://github.abc.com/abc/myabc',
description='This is a description for abc',
long_description=open('README.md').read(),
install_requires=[
"requests==2.7.0",
"SomePrivateLib>=0.1.0",
],
dependency_links = [
"git+git://github.abc.com/abc/SomePrivateLib.git#egg=SomePrivateLib",
],
include_package_data=True,
)

当我跑步的时候:

pip install -e https://github.abc.com/abc/myabc.git#egg=analyse

我明白

无法找到满足要求的版本 SomPrivateLib > = 0.1.0(来自分析)(来自版本:)没有匹配 Some PrivateLib > = 0.1.0(从分析中得出)

我做错了什么?

74768 次浏览

注意: 这个答案现在已经过时了,看看这个来自@Dick Fox 的最新说明: < a href = “ https://stackoverflow. com/a/54794506/2272172”> https://stackoverflow.com/a/54794506/2272172


你可以找到正确的方法来做它。

dependency_links=['http://github.com/user/repo/tarball/master#egg=package-1.0']

关键不是给出一个指向 Git 存储库的链接,而是一个指向 tarball 的链接。如果如上所示附加 /tarball/master,GitHub 将为您创建主分支的 tarball。

随着 Python 多年来的发展,这个问题的答案会定期更新。滚动到底部获得最新的答案,或者通读一遍,看看这是如何演变的。

不幸的是,另一个答案不适用于私有存储库,而私有存储库是最常见的用例之一。我最终使用 setup.py文件使它工作,该文件类似于下面这个(现在已经废弃)方法:

from setuptools import setup, find_packages


setup(
name = 'MyProject',
version = '0.1.0',
url = '',
description = '',
packages = find_packages(),
install_requires = [
# Github Private Repository - needs entry in `dependency_links`
'ExampleRepo'
],


dependency_links=[
# Make sure to include the `#egg` portion so the `install_requires` recognizes the package
'git+ssh://git@github.com/example_org/ExampleRepo.git#egg=ExampleRepo-0.1'
]
)

最新版本的 pip 通过去除使用“ Depency_ links”-的需要,使得这一点变得更加容易

from setuptools import setup, find_packages


setup(
name = 'MyProject',
version = '0.1.0',
url = '',
description = '',
packages = find_packages(),
install_requires = [
# Github Private Repository
'ExampleRepo @ git+ssh://git@github.com/example_org/ExampleRepo.git#egg=ExampleRepo-0.1'
]
)

然而,随着非常最新的点,你会遇到问题与 EGG 格式处理程序。这是因为,当 egg 被忽略时,pip 现在正在进行直接 URL 匹配,并将考虑两个 URL,一个带有 egg 片段,另一个没有,即使它们指向同一个包,也是完全不同的版本。因此,最好把鸡蛋的碎片留下。

2021年6月-setup.py

因此,从 Github 向 setup.py 添加依赖项的最佳方式(目前到2021年6月)是:

from setuptools import setup, find_packages


setup(
name = 'MyProject',
version = '0.1.0',
url = '',
description = '',
packages = find_packages(),
install_requires = [
# Github Private Repository
'ExampleRepo @ git+ssh://git@github.com/example_org/ExampleRepo.git'
]
)

2022年2月-setup.cfg

很明显,setup.py 已经被废弃了(尽管我猜它还会存在一段时间) ,setup.cfg 是一个新东西。

[metadata]
name = MyProject
version = 0.1.1




[options]
packages = :find


install_requires =
ExampleRepo @ git+ssh://git@github.com/example_org/ExampleRepo.git

2022年6月16日-pyproject. toml

Cfg 是 已经被“预先”否决了。作为 Setuptools 现在对 pyproject.toml 提供了实验性的支持文件。

这是未来的发展趋势,但是由于它仍然处于试验阶段,所以目前不应该在真正的项目中使用。即使 setup.cfg即将退出历史舞台,您也应该将其用于声明格式,否则 setup.py 仍然是可行的。当 setuptools 稳定了对新标准的支持时,这个答案将被更新。

在上面的评论中通过@muon 链接了 第3939期,然后是 PEP-508规范,我发现成功地使用 install_requires(不再是 dependency_links)中的规范模式通过 setup.py安装了我的私有回购依赖:

install_requires = [
'some-pkg @ git+ssh://git@github.com/someorgname/pkg-repo-name@v1.1#egg=some-pkg',
]

@v1.1表示在 github 上创建的发布标记,可以用分支、提交或不同类型的标记替换。

更一般的答案是: 要从 要求文件中获取信息,我需要:

from setuptools import setup, find_packages
from os import path


loc = path.abspath(path.dirname(__file__))


with open(loc + '/requirements.txt') as f:
requirements = f.read().splitlines()


required = []
dependency_links = []


# Do not add to required lines pointing to Git repositories
EGG_MARK = '#egg='
for line in requirements:
if line.startswith('-e git:') or line.startswith('-e git+') or \
line.startswith('git:') or line.startswith('git+'):
line = line.lstrip('-e ')  # in case that is using "-e"
if EGG_MARK in line:
package_name = line[line.find(EGG_MARK) + len(EGG_MARK):]
repository = line[:line.find(EGG_MARK)]
required.append('%s @ %s' % (package_name, repository))
dependency_links.append(line)
else:
print('Dependency to a git repository should have the format:')
print('git+ssh://git@github.com/xxxxx/xxxxxx#egg=package_name')
else:
required.append(line)


setup(
name='myproject',  # Required
version='0.0.1',  # Required
description='Description here....',  # Required
packages=find_packages(),  # Required
install_requires=required,
dependency_links=dependency_links,
)

实际上,如果你想让你的软件包可以递归安装(YourCurrentPackage 包括你的 Some PrivateLib) ,例如,当你想把 YourCurrentPackage 包含到另一个软件包中(比如 OuterPackage → YourCurrentPackage → Some PrivateLib) ,你需要两者兼备:

install_requires=[
...,
"SomePrivateLib @ git+ssh://github.abc.com/abc/SomePrivateLib.git@0.1.0#egg=SomePrivateLib"
],
dependency_links = [
"git+ssh://github.abc.com/abc/SomePrivateLib.git@0.1.0#egg=SomePrivateLib"
]

并确保使用版本号创建了一个标记。

此外,如果您的 Git 项目是私有的,并且您希望将其安装在容器中,例如,多克GitLab运行程序,那么您需要对存储库的授权访问。请考虑使用带访问令牌的 Git + HTTPS (如 GitLab: https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html) :

import os
from setuptools import setup


TOKEN_VALUE = os.getenv('EXPORTED_VAR_WITH_TOKEN')


setup(
....


install_requires=[
...,
f"SomePrivateLib @ git+https://gitlab-ci-token:{TOKEN_VALUE}@gitlab.server.com/abc/SomePrivateLib.git@0.1.0#egg=SomePrivateLib"
],
dependency_links = [
f"git+https://gitlab-ci-token:{TOKEN_VALUE}@gitlab.server.com/abc/SomePrivateLib.git@0.1.0#egg=SomePrivateLib"
]
)

更新:

如果您希望在 要求文件中具有此依赖项,则必须将 # egg = Some PrivateLib放在依赖项行的末尾。否则 Pip install-r requments.txt不会为你工作,你会得到这样的东西:

错误: 无法检测到 Git + https://gitlab-ci-token:gitlabtokenvalue@gitlab.server.com/abc/someprivatelib.git@0.1.0 请用 # egg = your _ package _ name 指定一个

如果使用 Reuirements.txt,这部分负责在 Python _ home _ dir/src中创建的依赖项文件夹的名称,以及在 网站-包装/中创建的 egg-link 的名称

你可以在你的 要求中使用一个环境变量来存储你的依赖的令牌值安全的在你的回购中:

这种情况下 请求文件中的示例行:

....


-e git+https://gitlab-ci-token:${EXPORTED_VAR_WITH_TOKEN}@gitlab.server.com/abc/SomePrivateLib.git@0.1.0#egg=SomePrivateLib
....

我在 GitLab中成功地使用了这三个选项。

选项1-没有指定令牌。 shell 将提示输入用户名/密码。

from setuptools import setup


TOKEN_VALUE = os.getenv('EXPORTED_VAR_WITH_TOKEN')


setup(
install_requires=[
"SomePrivateLib @ git+https://gitlab.server.com/abc/SomePrivateLib.git@0.1.0#egg=SomePrivateLib"
]
)

选项2-指定用户访问令牌。通过进入 GitLab →帐户右上角→设置→访问令牌生成的令牌。创建具有 read _ itory 权限的令牌。

例如:

import os
from setuptools import setup


TOKEN_VALUE = os.getenv('EXPORTED_VAR_WITH_TOKEN')


setup(
install_requires=[
f"SomePrivateLib @ git+https://gitlab-ci-token:{TOKEN_VALUE}@gitlab.server.com/abc/SomePrivateLib.git@0.1.0#egg=SomePrivateLib"
]
)

选项3-指定存储库级令牌。通过访问存储库→设置→存储库→部署令牌生成的令牌。从这里开始,创建一个具有 read _ itory 权限的令牌。

例如:

import os
from setuptools import setup


TOKEN_USER = os.getenv('EXPORTED_TOKEN_USER')
TOKEN_VALUE = os.getenv('EXPORTED_VAR_WITH_TOKEN')


setup(
install_requires=[
f"SomePrivateLib @ git+https://{TOKEN_USER}:{TOKEN_VALUE}@gitlab.server.com/abc/SomePrivateLib.git@0.1.0#egg=SomePrivateLib"
]
)

在这三个 https://gitlab.server.com/abc/SomePrivateLib.git" 中,我都可以做得很简单: “ Some Privatelib@git + ,结尾没有 # egg 标记。

当我运行 python setup.py install 时,这个解决方案对我很有用:

setuptools.setup(
...,
install_requires=[
'numpy',
'pandas',
'my_private_pkg'
],
dependency_links=["git+https://github.com/[username]/[my_private_pkg].git@main#egg=my_private_pkg"],
...
)