【问题标题】:I want to know the url pip has used to download a package (.whl file)我想知道 pip 用于下载包(.whl 文件)的 url
【发布时间】:2022-11-05 03:30:01
【问题描述】:

我需要 pip 用于从 Internet 下载包的 URL 列表,最好使用 requirements.txt 文件中的 python 包列表。

您知道解决此问题的快速简便的方法吗?也许那里有一个工具或我不知道的 pip 功能?

我需要知道下载地址没有安装软件包。我可以下载包 .whl 文件。

我尝试使用 pip download -r requirements.txt 将文件从 pypi 下载到我的计算机。我可以使用wireshark查看网络上的url。我不知道如何以编程方式获取用于下载文件的 url。

【问题讨论】:

标签: python pip pypi


【解决方案1】:

您可以在命令提示符中使用pip show <package-name> 命令。这将显示可以在Home-page 下找到包的网址。

例如:

> pip show gym
Name: gym
Version: 0.26.1
Summary: Gym: A universal API for reinforcement learning environments
Home-page: https://www.gymlibrary.dev/
Author: Gym Community
Author-email: jkterry@umd.edu
License: MIT
Location: C:path	opackages
Requires: cloudpickle, gym-notices, numpy
Required-by:

【讨论】:

  • 如果安装了软件包,这只会显示 url 吗?但是我不打算安装这些软件包。我只想知道他们在哪里。我可以下载 .whl 文件。但是安装不是一个选项....如果我在尚未安装的包上尝试此操作,我会收到:“警告:找不到包:<包>”错误
【解决方案2】:

此 python 代码将自动解析本地 requirements.txt 文件中提到的所有包的 html 站点。结果是一个名为urls 的列表。

注意:除非您在执行此代码的同一目录中有requirements.txt 的副本,否则这将不起作用。

import requests as req
from bs4 import BeautifulSoup as parser

f = open("requirements.txt", 'r').read().split('
')
requirements = []
for line in f:
    if '==' in line:
        for i in range(len(line)):
            if line[i:i+2] == '==':
                requirements.append("https://pypi.org/project/" + line[:i])
                break

urls = []
for r in requirements:
    p = parser(req.get(r).content, "html.parser")
    url = str(p.find("div", class_="card file__card").find("a")).split("<a href="")[1].split(""")[0]
    urls.append(url)

print(urls)

【讨论】:

  • 这是一个非常复杂的解决方案,并且仅适用于要求具有锁定版本“==”的情况(如果您正在解析锁定文件,这没什么大不了的)。它也不适用于额外的包等。如果您有兴趣,我发布了一个更简单的解决方案,它不会将 html 解析为这个问题的答案。不过,我仍然会尝试找到更好的方法。诗歌或许就是答案。
【解决方案3】:

我发现我可以通过在 https://pypi.org/pypi//json 手动解析 json 来找到特定发行版本的下载 url。

遗憾的是 pip 默认没有实现这个功能。特别是对于那些想要在安装前以编程方式检查下载完整性的人。

我找到的解决方案需要将版本锁定在 '==' (如果我改为解析锁定文件,这没什么大不了的)。也不处理“附加”等。我正在寻找一种使用诗歌的方法(解析由诗歌生成的 requirements.txt 文件似乎比处理用户定义的需求中发现的所有边缘情况更容易。 txt 文件)。

我的解决方案:

def get_packages_from_lock_file(lock_file):
    # regexp example text to match: black==22.1.0
    # Regex is neccesary as requirements.txt can have hashes and python version requirements in them.
    packages = re.findall(r'([_-a-zA-Z0-9]+)==(d+.d+.d+)', lock_file)
    # example return: [
    #     ('black', '22.10.0'),
    #     ('click', '8.1.3'),
    #     ('colorama', '0.4.6'),
    # ]
    return packages


# pip show only shows urls of installed packages. We dont want to install package to see the url
# pip has no way of doing this currently so I am manually parsing the pip package json for the url
def show_package_url(package):
    name = package[0].strip()
    version = package[1].strip()
    try:
        package_json = requests.get(url=f"https://pypi.org/pypi/{name}/json").json()
        # package version seems to usually contain a .whl file for pip installation and a tar.gz file for direct use
        # TODO: do we need to download both files or allow the user an option to choose?
        package_json_version = package_json["releases"][version]
        return [file["url"] for file in package_json_version]
    except HTTPError as ex:
        raise ex

    packages = get_packages_from_requirements(requirements_file)
    for package in packages:
        package_urls = show_package_url(package)
        for url in package_urls:
            job.add_url(url)

【讨论】:

猜你喜欢
  • 2018-06-27
  • 2020-09-12
  • 2016-11-22
  • 2021-04-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-19
相关资源
最近更新 更多