如何在requirements.txt中声明直接从Github获取的源码

770

我使用命令安装了一个库

pip install git+git://github.com/mozilla/elasticutils.git

这将直接从Github代码库安装该依赖项。这很好用,我希望在我的requirements.txt中有这个依赖项。我查看了其他帖子,比如这个,但那并没有解决我的问题。如果我添加这样的内容:

-f git+git://github.com/mozilla/elasticutils.git
elasticutils==0.7.dev

requirements.txt 文件中,运行 pip install -r requirements.txt 命令会产生以下输出:

Downloading/unpacking elasticutils==0.7.dev (from -r requirements.txt (line 20))
  Could not find a version that satisfies the requirement elasticutils==0.7.dev (from -r requirements.txt (line 20)) (from versions: )
No distributions matching the version for elasticutils==0.7.dev (from -r requirements.txt (line 20))

需求文件的文档没有提到使用git+git协议说明符的链接,因此可能不支持。

有人有解决我的问题的方法吗?

10个回答

954

通常你的requirements.txt文件看起来会像这样:

package-one==1.9.4
package-two==3.7.1
package-three==1.0.1
...

要指定Github存储库,您不需要使用package-name==约定。

以下示例使用GitHub存储库更新package-two@后面的文本表示软件包的具体信息。

指定提交哈希值(在更新requirements.txt的上下文中为41b95ec):

package-one==1.9.4
package-two @ git+https://github.com/owner/repo@41b95ec
package-three==1.0.1

指定分支名称(main):

package-two @ git+https://github.com/owner/repo@main

指定标签(0.1):

package-two @ git+https://github.com/owner/repo@0.1

指定发布版本 (3.7.1):

package-two @ git+https://github.com/owner/repo@releases/tag/v3.7.1

请注意,在某些版本的pip中,您需要在软件包的setup.py中更新软件包版本,否则pip将假定要求已经满足并且不会安装新版本。例如,如果您已经安装了1.2.1,并且想要使用自己的版本分叉此软件包,则可以在您的requirements.txt中使用上述技术,然后将setup.py更新为1.2.1.1
另请参阅pip文档关于VCS支持

144
在所有其他的回答中,我不敢相信没有一个只是展示了一个带有混合“常规”要求和Git要求以进行比较的要求文件。我被看起来像命令行(-e)选项的东西所迷惑了。感谢您展示了两者的混合,让我可以将其放入上下文中! - Hendy
5
指向发布版本3.7.1的方式git+git://github.com/path/to/package-two@releases/tag/v3.7.1#egg=package-two对我不起作用。对我有用的是git+git://github.com/path/to/package-two@3.7.1#egg=package-two - Jean Paul
13
这个答案非常有帮助。但是有一个问题,使用git+git://...这种表示方法会在我的Linux系统上导致ssh相关的错误。所以我最终将它们切换到git+https://...这种表示方法,然后它们就完美地工作了。 - RayLuo
2
我不确定egg=<package name>应该填什么。我fork了一个项目,其中你用pip install安装的包名中有一个破折号(package-two),但你导入的模块中有一个下划线(package_two)。我使用了导入模块的名称(带下划线),它可以正常工作。 - ChrisCrossCrash
9
GitHub不再支持git协议,你需要使用https。 - MikeTwo
显示剩余9条评论

390

4
由于语法问题,我没有成功地在本地完成可编辑版本的结帐,因此最终使用了git+git变体(这个可以工作)。在requirements.txt中,您的版本是有效的,非常感谢 :) - Alfe
51
我理解不了的是,所展示的语法正是在需求中所需要使用的,也就是说,在-e之前没有包名。 - sage
6
根据@qff的回答,是否需要将包添加“-e”取决于您是否希望在可编辑模式下使用该包。 - Tianwei Chen
17
应该是 -e git+git:// 而不是 -e git:// 吗?我收到了一个错误提示 "应该是一个本地项目的路径或者以 svn+、git+、hg+ 或 bzr+ 开头的版本控制系统 URL。"。 - Srini
2
我得到了这个错误信息 无法检测到要求名称,请使用 #egg= 指定一个名称 - abbood
显示剩余7条评论

210

requirements.txt 允许在 pip 7.0 中以以下方式指定对 git 存储库中软件包的依赖:1

[-e] git+git://git.myproject.org/SomeProject#egg=SomeProject
[-e] git+https://git.myproject.org/SomeProject#egg=SomeProject
[-e] git+ssh://git.myproject.org/SomeProject#egg=SomeProject
-e git+git@git.myproject.org:SomeProject#egg=SomeProject (deprecated as of Jan 2020)

对于 Github 而言,这意味着你可以执行以下操作(注意省略了 -e):

git+git://github.com/mozilla/elasticutils.git#egg=elasticutils

为什么要额外回答?
我对其他答案中的-e标志有些困惑,因此在这里进行澄清:

-e--editable标志意味着包被安装在<venv路径>/src/SomeProject中,而不是它本应该放置在深埋的<venv路径>/lib/pythonX.X/site-packages/SomeProject中。2

文档


14
请注意,如果您省略 -e,则下一次运行 pip freeze 可能无法正确地列出此软件包的结果。 - Maccesch
5
注意:自2020年1月起,git+git@类型的URL已被弃用(参见pip问题#7554)。其他类型的URL仍然受支持。 - idbrii
ssh的语法是git+ssh://git@git.myproject.org/SomeProject#egg=SomeProject - undefined

102

首先,以任何你熟悉的方式使用git+gitgit+https安装。以下是安装brabeion项目的kronok分支的示例:

pip install -e git+https://github.com/kronok/brabeion.git@12efe6aa06b85ae5ff725d3033e38f624e0a616f#egg=brabeion

第二步,使用pip freeze > requirements.txt命令将正确的信息获取到你的requirements.txt文件中。这样做可以得到以下内容:

-e git+https://github.com/kronok/brabeion.git@12efe6aa06b85ae5ff725d3033e38f624e0a616f#egg=brabeion-master

第三步,测试结果:

pip uninstall brabeion
pip install -r requirements.txt

6
pip freeze 仍然将我使用的软件包列为先前关闭的版本,而不是直接从 GitHub 检出。 - Antoine Claval
5
您需要在使用“pip freeze”命令时添加“-e”选项来生成一个URL。 - Janusz Skonieczny
3
pip 9.0.1: no such option: -e 的翻译是:pip 9.0.1版本出现错误,提示“无此选项:-e”。 - sds
你是指 git+https 吗?在文本中你说的是 git+git,而在代码中是 git+https - Antony Hatchkins
@AntonyHatchkins 已修复。 - Sergey Orshanskiy
这种方法至少让我找到了Bitbucket的正确语法。例如,如果我的包名称是“fred”,我可以使用以下方案:pip install -e git+ssh://bitbucket.org/mybitbucketaccount/fred.git@397783bc10d5b13c7d5078d4368402aabcd05fb8#egg=fred - Jeff Wright

25

自pip v1.5版本以来(发布于2014年1月1日:CHANGELOGPR),您也可以指定git存储库的子目录来包含您的模块。 语法看起来像这样:

pip install -e git+https://git.repo/some_repo.git#egg=my_subdir_pkg&subdirectory=my_subdir_pkg # install a python package from a repo subdirectory

注意:作为pip模块的作者,理想情况下,您可能希望将自己的模块发布在其自己的顶级存储库中。但是,如果一些预先存在的存储库包含子目录中的Python模块,则此功能可能会有所帮助。如果它们没有发布到pypi,则您可能需要以这种方式安装它们。


17

Github有zip端点,我认为比使用Git协议更可取。好处是:

  • 您不必指定#egg=<项目名称>
  • 您的环境中不需要安装Git,这在容器化环境下很好
  • 它与pip哈希和缓存配合得更好
  • URL结构更易于记忆和发现

通常,您希望requirements.txt条目看起来像这样,例如没有-e前缀:

https://github.com/org/package/archive/1a58aa586efd4bca37f2cfb9d9348958986aab6c.tar.gz

安装主分支:

https://github.com/org/package/archive/main.tar.gz

还有一个等效的.zip端点,但是在评论中报告说始终使用.tar.gz端点可以避免使用Unicode软件包名称时出现问题。

等效的.zip端点也存在,但据评论报道,总是使用.tar.gz端点可以避免Unicode软件包名称方面的问题。

4
如同在此类似的SO答案的评论中提到的,压缩包提取程序可能会在使用Unicode软件包名称时出现问题。指定.tar.gz而非.zip可以解决这个问题。 - ryanjdillon
1
@ryanjdillon 我更新了答案,建议使用.tar.gz而不是.zip - antonagestam
这是我一直在寻找的答案,谢谢。 - ramnes
唯一不需要指定 egg=package 的情况是当包有一个适当的名称,并且只有一个包,pip会找到并翻译。这种假设是不安全的。GitHub提供的压缩文件也不会改变这一点,你测试过的存储库使用git+https超链接或zip“端点”都会产生相同的效果。 - undefined

16

这些答案都对我没用。唯一有效的是:

git+https://github.com/path_to_my_project.git

无需“e”,无需双“git”,也无需先前的安装。


-e的意思是将软件包安装为可编辑的软件包,这可能是可取的,也可能不可取,这取决于软件包本身以及您将如何使用它。 - undefined

8

看起来这也是一个有效的格式:

gym-tictactoe @ git+https://github.com/haje01/gym-tictactoe.git@84e22fc28fe192ba0040bdd56a697f63d3d4a3d5

如果您运行 pip install "git+https://github.com/haje01/gym-tictactoe.git" 命令安装了该包,然后通过 pip freeze 查看安装的内容,您将看到以此格式描述的软件包,并且可以将其复制并粘贴到 requirements.txt 文件中。

这修复了我在 private reposetup.pyinstall_requires 选项上的问题。谢谢! - Nathaniel Varona
1
今天刚好需要这个,但是以前的答案中的解决方案对我没有用,但是这个解决方案很好用。我想知道pip是否有变化?特别是在末尾的#egg=gym-tictactoe失败了,但是在开头的gym-tictactoe @ 中使用相同的git+https:... URL可以工作。 - someone
这是不可编辑包的语法(不带-e选项)。 - undefined

5

我发现,对于通过Ubuntu 18.04的包管理器安装的pip3(v9.0.1),让它真正安装我所告诉它要安装的东西有点棘手。 我发布这个答案是为了节省任何遇到这个问题的人的时间。

将此内容放入requirements.txt文件中失败了:

git+git://github.com/myname/myrepo.git@my-branch#egg=eggname

在这里所说的"failed"指的是虽然从Git下载了代码,但最终安装的是在PyPi上找到的原始版本的代码,而不是该分支上repo中的代码。

然而,安装commit而不是分支名称可以解决这个问题:

git+git://github.com/myname/myrepo.git@d27d07c9e862feb939e56d0df19d5733ea7b4f4d#egg=eggname

你确定你的分支也是远程的吗? - Alfe
它并未指向本地副本,如果你在想这个的话。 - Throw Away Account
这个语法现在已经被弃用了,对于公共的 GitHub 仓库,现在使用 git+https,而对于私有仓库,则使用 git+ssh - undefined
@IuriGuilherme 你能给一个使用git+ssh的例子吗?我尝试了pip install git+ssh://git@github.com:user/repo.git,但是它会自动添加****并尝试执行git clone --filter=blob:none --quiet 'ssh://****@github.com:user/repo.git' 'C:\Users\userame\AppData\Local\Temp\pip-req-build-x2x6s19c',这导致出现以下错误信息: `ssh: Could not resolve hostname github.com:user: Name or service not known fatal: Could not read from remote repository. Please make sure you have the correct access rights and the repository exists.` - undefined
@Adriaan 语法是 pip install 'git+ssh://git@github.com/user/repo.git' 或者完整版本 pip install 'git+ssh://git@somewebsite.com/someoneusername/somerepositoryname.git@1234567890abcdef#egg=packagename'(我包含了引号以进行shell转义)。 - undefined

4

对于私有仓库,我发现以下两种方法适合我:

pip install https://${GITHUB_TOKEN}@github.com/owner/repo/archive/main.tar.gz

“main.tar.gz” 是您存储库中的“main”分支,可以替换为其他分支名称。有关更多信息和使用最新的 Github API,请参见这里

pip install https://${GITHUB_TOKEN}@api.github.com/repos/owner/repo/tarball/master

如果您已经安装并且使用了 git,那么:
pip install git+https://${GITHUB_TOKEN}@github.com/owner/repo.git@main

实现相同的功能,同时还可以通过添加@branch@tag@commit-hash来获得更多的灵活性。然而,这种方法实际上会将存储库克隆到本地临时文件夹中,这可能需要一定的时间。

您也可以在您的requirements.txt中使用这些URL。


对于私有仓库,有git+ssh规范,认证是通过同一shell中的ssh程序处理的。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接