查看原文
其他

Python脚本设置pip索引源,一键加速

carry麦 码农真经 2023-12-25
pypi

背景

Python[1] 包索引(Python Package Index,PyPI)是由全球 Python 开发人员社区提供的大量开源 Python 包的存储库。官方索引在 https://pypi.org,网站本身由 Python 软件基金会(Python Software Foundation,PSF)维护。 你也可以在上面发布自己的项目,可参考 A Beginner’s Guide to Publishing Packages on the Python Package Index (PyPi)[2]How to Publish an Open-Source Python Package to PyPI[3]

Python 使用 pip[4] 安装第三方包时,默认使用的官方索引源 pypi[5] 的地址 https://pypi.python.org/pypi 在中国大陆因为墙的原因,下载缓慢。 跟 ubuntu[6] 的 apt[7] 和 archlinux[8] 的 Pacman[9] 有各自国内镜像源一样,pip 也有国内索引源可用,下面罗列了一部分,进一步的,为了便于设置国内源,并受到 nodejs[10] 的 nrm[11] 的启发,我编写了一个脚本[12]

keyindex-urltrusted-url提供者
doubanhttp://pypi.douban.com/simple/pypi.douban.com豆瓣
aliyunhttp://mirrors.aliyun.com/pypi/simple/mirrors.aliyun.com阿里云
tsinghuahttps://pypi.tuna.tsinghua.edu.cn/simple/pypi.tuna.tsinghua.edu.cn清华大学
ustchttps://pypi.mirrors.ustc.edu.cn/simple/pypi.mirrors.ustc.edu.cn中国科学技术大学
hustuniquehttp://pypi.hustunique.com/simple/pypi.hustunique.com华中理工大学
sdutlinuxhttp://pypi.sdutlinux.org/simple/pypi.sdutlinux.org山东理工大学
tencenthttp://mirrors.cloud.tencent.com/pypi/simple/mirrors.cloud.tencent.com腾讯云

以豆瓣源为例,假设要安装 pandas[13] 可执行如下命令

pip install -i http://pypi.douban.com/simple/ --trusted-host=pypi.douban.com/simple pandas

如果写到配置文件[14],便可不用每次指定 -i 参数

pip config set global.index-url http://pypi.douban.com/simple/
pip config set install.trusted-host pypi.douban.com

所有的 pip 配置文件路径,可以用如下命令获取

python -c "from pip._internal.configuration import get_configuration_files;print(get_configuration_files())"

代码实现

TIPS 代码的最新版本在 GitHub Gist[15] 中维护 https://gist.github.com/ChenyangGao/61d5e6eeb149a38291128fcd35befffc

文件名称是 pip_index.pyPython 实现代码如下:

#!/usr/bin/env python3
# coding: utf-8

"""\
Tool for setting the index-url of pip

Reference: 
- https://pip.pypa.io/en/latest/
- https://docs.python.org/3/installing/index.html
- https://docs.python.org/3/library/ensurepip.html
"""

assert __name__ == "__main__", "Can only be used as __main__ module"

__author__ = "ChenyangGao <https://chenyanggao.github.io/>"
__version__ = (0, 1)

from argparse import ArgumentParser, RawTextHelpFormatter


parser = ArgumentParser(
    description="Python pip 源配置工具", 
    formatter_class=RawTextHelpFormatter, 
)
subparsers = parser.add_subparsers(dest="command", help="Available commands")

parser_list = subparsers.add_parser(
    "list", formatter_class=RawTextHelpFormatter, 
    help="罗列所有可用的源", description="""罗列所有可用的源,格式形如
{key}: 
    index-url: {index_url!r}
    trusted-host: {trusted_host!r}
    comment: {comment!r}""")

parser_use = subparsers.add_parser(
    "use", formatter_class=RawTextHelpFormatter, 
    help="使用 key 指定要设置的源", description="使用 key 指定要设置的源")
parser_use.add_argument(
    "key", default="pypi", nargs="?", help="key,对应某个源,默认值 pypi")
parser_use.add_argument(
    "-k", "--kind", default="user", choices=("global", "user", "site"), 
    help="""类型,默认值 user
  - global  Use the system-wide configuration file only
  - user    Use the user configuration file only
  - site    Use the current environment configuration file only""",
)
parser_use.add_argument(
    "-i", "--isolated", action="store_true",
    help="Run pip in an isolated mode, ignoring environment "
         "variables and user configuration.")
parser_use.add_argument(
    "-c", "--cmd-only", dest="cmd_only", action="store_true",
    help="并不设置配置文件,只是打印一个 pip install 命令"
)

args = parser.parse_args()


from pip._internal.configuration import Configuration
from urllib.parse import urlsplit


# TIPS: 20 == logging.INFO
__import__("logging").basicConfig(level=20, format="%(message)s")

INDEXES = {
    "pypi": {
        "index-url": "https://pypi.python.org/pypi",
        "trusted-host": "pypi.python.org",
        "comment": "官方源"
    },
    "douban": {
        "index-url": "http://pypi.douban.com/simple/",
        "trusted-host": "pypi.douban.com",
        "comment": "豆瓣"
    },
    "aliyun": {
        "index-url": "http://mirrors.aliyun.com/pypi/simple/",
        "trusted-host": "mirrors.aliyun.com",
        "comment": "阿里云"
    },
    "tsinghua": {
        "index-url": "https://pypi.tuna.tsinghua.edu.cn/simple/",
        "trusted-host": "pypi.tuna.tsinghua.edu.cn",
        "comment": "清华大学"
    },
    "ustc": {
        "index-url": "https://pypi.mirrors.ustc.edu.cn/simple/",
        "trusted-host": "pypi.mirrors.ustc.edu.cn",
        "comment": "中国科学技术大学"
    },
    "hustunique": {
        "index-url": "http://pypi.hustunique.com/simple/",
        "trusted-host": "pypi.hustunique.com",
        "comment": "华中理工大学"
    },
    "sdutlinux": {
        "index-url": "http://pypi.sdutlinux.org/simple/",
        "trusted-host": "pypi.sdutlinux.org",
        "comment": "山东理工大学"
    }, 
    "tencent": {
        "index-url": "http://mirrors.cloud.tencent.com/pypi/simple/",
        "trusted-host": "mirrors.cloud.tencent.com",
        "comment": "腾讯云"
    }, 
}


def pipi_list():
    "罗列所有可用的源"
    for key, index in INDEXES.items():
        print("%s: %s" % (key,
            "".join("\n    %s: %r" % e for e in index.items())))


def pipi_use(key="pypi", kind="user", isolated=False):
    """使用 key 指定要设置的源

    :param key: key,对应某个源,默认值 pypi
    :param kind: 类型,默认值 user
        - global  Use the system-wide configuration file only
        - user    Use the user configuration file only
        - site    Use the current environment configuration file only
    :param isolated: Run pip in an isolated mode, ignoring environment 
        variables and user configuration.
    """
    # assert kind in ("global", "user", "site")
    index = INDEXES[key]
    index_url = index["index-url"]
    trusted_host = index.get("trusted-host") or urlsplit(index_url).netloc
    conf = Configuration(isolated, kind)
    conf.load()
    conf.set_value("global.index-url", index_url)
    conf.set_value("install.trusted-host", trusted_host)
    conf.save()


command = args.command
if command == "list":
    pipi_list()
elif command == "use":
    if args.cmd_only:
        from sys import executable

        index = INDEXES[args.key]
        index_url = index["index-url"]
        trusted_host = index.get("trusted-host") or urlsplit(index_url).netloc
        print(f"'{executable}' -m pip install --index-url "
              f"{index_url} --trusted-host {trusted_host} ")
    else:
        pipi_use(args.key, args.kind, args.isolated)
else:
    raise NotImplementedError(f"Command {command!r} is not implemented!")

使用说明

命令帮助信息如下:

$ python pip_index.py -h
usage: pip_index.py [-h] {list,use} ...

Python pip 源配置工具

positional arguments:
  {list,use}  Available commands
    list      罗列所有可用的源
    use       使用 key 指定要设置的源

optional arguments:
  -h, --help  show this help message and exit

不同的系统和用户,命令输出的结果会有不同,我的环境如下:

# 我当前用的 Linux 发行版
uname -a
Linux kali 5.16.0-kali3-amd64 #1 SMP PREEMPT Debian 5.16.11-1kali1 (2022-03-03) x86_64 GNU/Linux
# 当前的用户
whoami
kali

1. list 命令

命令帮助信息如下:

$ python pip_index.py list -h
usage: pip_index.py list [-h]

罗列所有可用的源,格式形如
{key}: 
    index-url: {index_url!r}
    trusted-host: {trusted_host!r}
    comment: {comment!r}

optional arguments:
  -h, --help  show this help message and exit

执行如下命令示例:

python pip_index.py list         
pypi: 
    index-url: 'https://pypi.python.org/pypi'
    trusted-host: 'pypi.python.org'
    comment: '官方源'
douban: 
    index-url: 'http://pypi.douban.com/simple/'
    trusted-host: 'pypi.douban.com'
    comment: '豆瓣'
aliyun: 
    index-url: 'http://mirrors.aliyun.com/pypi/simple/'
    trusted-host: 'mirrors.aliyun.com'
    comment: '阿里云'
tsinghua: 
    index-url: 'https://pypi.tuna.tsinghua.edu.cn/simple/'
    trusted-host: 'pypi.tuna.tsinghua.edu.cn'
    comment: '清华大学'
ustc: 
    index-url: 'https://pypi.mirrors.ustc.edu.cn/simple/'
    trusted-host: 'pypi.mirrors.ustc.edu.cn'
    comment: '中国科学技术大学'
hustunique: 
    index-url: 'http://pypi.hustunique.com/simple/'
    trusted-host: 'pypi.hustunique.com'
    comment: '华中理工大学'
sdutlinux: 
    index-url: 'http://pypi.sdutlinux.org/simple/'
    trusted-host: 'pypi.sdutlinux.org'
    comment: '山东理工大学'
tencent: 
    index-url: 'http://mirrors.cloud.tencent.com/pypi/simple/'
    trusted-host: 'mirrors.cloud.tencent.com'
    comment: '腾讯云'

2. use 命令

命令帮助信息如下:

$ python pip_index.py use -h 
usage: pip_index.py use [-h] [-k {global,user,site}] [-i] [-c] [key]

使用 key 指定要设置的源

positional arguments:
  key                   key,对应某个源,默认值 pypi

optional arguments:
  -h, --help            show this help message and exit
  -k {global,user,site}, --kind {global,user,site}
                        类型,默认值 user
                          - global  Use the system-wide configuration file only
                          - user    Use the user configuration file only
                          - site    Use the current environment configuration file only
  -i, --isolated        Run pip in an isolated mode, ignoring environment variables and user configuration.
  -c, --cmd-only        并不设置配置文件,只是打印一个 pip install 命令

执行如下命令示例:

$ python pip_index.py use douban
Writing to /home/kali/.config/pip/pip.conf
cat /home/kali/.config/pip/pip.conf
[global]
index-url = http://pypi.douban.com/simple/

[install]
trusted-host = pypi.douban.com

$ pip config list                    
global.index-url='http://pypi.douban.com/simple/'
install.trusted-host='pypi.douban.com'
# 如果仅仅只是想要使用源,而不想修改配置文件,
# 可以用下面的命令打印一个 pip install 命令,
# 复制后在命令行粘贴,然后在后面添加要安装的模块
$ python pip_index.py use douban -c
'/home/kali/anaconda3/bin/python' -m pip install --index-url http://pypi.douban.com/simple/ --trusted-host pypi.douban.com 

往期推荐

欢迎关注我的公众号“码中人”,原创技术文章第一时间推送。

引用链接

[1] Python: https://www.python.org
[2] A Beginner’s Guide to Publishing Packages on the Python Package Index (PyPi): https://medium.com/analytics-vidhya/a-beginners-guide-to-publishing-packages-on-the-python-package-index-pypi-a0157e13c174
[3] How to Publish an Open-Source Python Package to PyPI: https://realpython.com/pypi-publish-python-package/
[4] pip: https://pypi.org/project/pip/
[5] pypi: https://pypi.org
[6] ubuntu: https://ubuntu.com
[7] apt: https://salsa.debian.org/apt-team/apt
[8] archlinux: https://archlinux.org
[9] Pacman: https://github.com/terralinux/pacman
[10] nodejs: https://nodejs.org
[11] nrm: https://www.npmjs.com/package/nrm
[12] 脚本: https://gist.github.com/ChenyangGao/61d5e6eeb149a38291128fcd35befffc
[13] pandas: https://pandas.pydata.org
[14] 配置文件: https://pip.pypa.io/en/stable/topics/configuration/
[15] GitHub Gist: https://gist.github.com/ChenyangGao


继续滑动看下一个

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存