Python 管理 —— 包管理
老规矩,在文章开始之前先简单罗列一下基本环境:
- 操作系统(OS):Ventura 13.4
- Python 版本:3.11.3
- pip 版本:23.1.2
Pyhton 的强大来源于其丰富的第三方库,自然在使用 Python 的时候不可避免的会需要用到一些第三方库,那么,如何高效地对这些第三方库进行查找、安装和卸载等等操作,都是包管理涉及的内容。
pip 是官方提供给的一个 Python 包管理工具1,pip 提供了对 Python 包进行的查找、下载、安装以及卸载等功能。下面要介绍的 Python 包管理的内容,也是围绕着 pip 工具展开的。
pip 的安装
注意:一般情况下,如果是从官网 Python.org 下载的 Python 会默认安装 pip.
利用 Python 下载时自带的 ensurepip
模块,可以对 pip 进行安装:
1 | python -m ensurepip --upgrade |
python
:Python 的解释器,默认使用的解释器是CPython
,用>>>
作为提示符2-m ensurepip
:在sys.path
下搜索ensurepip
的模块,并把相应的.py
文件作为脚本运行,--upgrade
作为ensurepip
的模块的参数sys.path
:模块的搜索路径,可以通过在 Python 的交互环境中import sys
,将sys.path
打印出来31
2
3import sys
sys.path
['', '/usr/local/Cellar/python@3.11/3.11.3/Frameworks/Python.framework/Versions/3.11/lib/python311.zip', '/usr/local/Cellar/python@3.11/3.11.3/Frameworks/Python.framework/Versions/3.11/lib/python3.11', '/usr/local/Cellar/python@3.11/3.11.3/Frameworks/Python.framework/Versions/3.11/lib/python3.11/lib-dynload', '/usr/local/lib/python3.11/site-packages']
可以简单看一下 ensurepip
模块的内容,发现 ensurepip
模块其实是一个文件夹:
1 | cd /usr/local/Cellar/python@3.11/3.11.3/Frameworks/Python.framework/Versions/3.11/lib/python3.11/ && ls -l | grep -i ensurepip |
1 | drwxr-xr-x 7 borne admin 224 4 22 20:16 ensurepip |
通过 tree
命令查看 ensurepip
文件目录:
1 | tree ensurepip |
1 | ensurepip |
进一步发现,由于 __init__.py
标识文件的存在,ensurepip
其实更确切的说是一个包(Package)。
通过 cat
命令,查看一下 __init__.py
文件:
1 | cat ensurepip/__init__.py | more |
其中,有这样一段代码:
1 | parser = argparse.ArgumentParser(prog="python -m ensurepip") |
这就解释了,为什么可以通过 python -m ensurepip --upgrade
安装 pip.
关于 pip 的安装,还有最后一点需要强调的是,一个版本的 Python 对应了一个 pip 工具,理解这一点,对于电脑中存在多个版本的 Python 时尤其的重要,每个 Python 都有自己的 pip 工具,所以,当在使用 pip 工具安装第三方库时,一定要清楚,你当时使用的 pip 属于哪个版本的 Python(这个问题本质上是电脑的环境变量的配置问题),其实这也侧面体现出后面要介绍的 Python 版本管理 和 环境管理的意义和重要性。
如果不清楚当前的 pip 命令属于哪个版本的 Python,可以用 which
或 whereis
命令,再结合 ls -l
命令简单查询一下:
1 | which pip3 |
1 | /usr/local/bin/pip3 |
1 | ls -l /usr/local/bin/pip3 |
1 | lrwxr-xr-x 1 borne admin 37 4 22 20:16 /usr/local/bin/pip3 -> ../Cellar/python@3.11/3.11.3/bin/pip3 |
从上面的结果可以看出,这里的 pip3
对应的是 python@3.11
,所以,通过 pip3
安装的第三方库,其实是安装到了 python@3.11
的 site-packages
下。
pip 基本语法
1 | python -m pip <pip arguments> |
python -m pip
:使用你指定为python
的 Python 解释器去执行pip
提示:也可以直接运行
pip <pip arguments>
,但是,还是前面说的那个问题,在运行时要清楚这个pip
属于谁,当然python -m pip
也存在同样的问题,运行时也同样要清楚python
属于哪个版本。
pip 常用的命令
pip 自更新
1 | python -m pip install --upgrade pip |
pip 安装 Packages
第一种安装方式,也是最常见的情况,使用 Requirement Specifiers4 从 PyPI 安装:
1 | python -m pip install SomePackage # latest version |
第二种安装方式,在项目中常用,使用 requirements
文件5进行安装:
1 | python -m pip install -r requirements.txt |
requirements
文件常常配合着 pip freeze
命令进行使用,将 pip freeze
的结果保存到 requirements
文件中:
1 | python -m pip freeze > requirements.txt |
第三种安装方式,通过 wheel
进行安装6:
1 | python -m pip install SomePackage-1.0-py2.py3-none-any.whl |
其实,如果阅读得仔细的话,到这也许就会意识到,前面在对 pip 进行安装时,用到的 ensurepip
包内其实有 pip-23.0.1-py3-none-any.whl
pip 卸载 Packages
1 | python -m pip uninstall SomePackage |
注意:pip 还会在升级到新版本之前自动卸载旧版本的包
pip 列出 Packages
列出已安装的包:
1 | python -m pip list |
列出过时的包,并显示可用的最新版本:
1 | python -m pip list --outdated |
显示有关已安装包的详细信息:
1 | python -m pip show sphinx |
pip 搜索 Packages
pip 可以使用 pip search
命令在 PyPI 中搜索包:
1 | python -m pip search "query" |
Notes:PyPI no longer supports 'pip search' (or XML-RPC search). Please use https://pypi.org/search (via a browser) instead.
pip 其它的命令
pip 命令补全
pip 支持 bash、zsh 和 fish 中的命令行补全。
为 bash 设置命令行补全:
1 | python -m pip completion --bash >> ~/.profile |
为 zsh 设置设置命令行补全:
1 | python -m pip completion --zsh >> ~/.zprofile |
pip freeze
以需求格式输出已安装的包,包以不区分大小写的排序顺序列出。
1 | python -m pip freeze |
1 | docutils==0.11 |
pip 配置
pip 允许用户通过 3 种机制更改其行为7:
- command line options 命令行选项(利用
pip config
命令) - environment variables 环境变量
- configuration files 配置文件
可以对 pip 进行一些个性化的设置,比如:当下载第三库速度太慢时,可以通过设置镜像源加快下载速度。
下面将主要介绍两个比较常用的更改方式:命令行选项和配置文件。
pip config
命令行选项覆盖环境变量,环境变量覆盖配置文件中的值。即:通过命令行选项进行设置的优先级最高。
列出配置文件及其下定义的值:
1 | python -m pip config debug |
查询某一个具体的配置:
1 | python -m pip config get command.option |
设置/重置某一个具体的配置:
1 | python -m pip config [<file-option>] set/unset command.option value |
具体实例:
通过命令行选项设置镜像源
1 | python -m pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple |
通过命令行选项设置 pip 日志
1 | python -m pip config set global.log /var/log/pip.log |
pip 配置文件
配置文件可以更改命令行选项的默认值。它们是使用标准 INI 格式的配置文件编写的。
pip 有 3 个 "级别" 的配置文件:
global
:系统范围的配置文件,跨用户共享user
:每个用户的配置文件site
:每个环境的配置文件,即:每个虚拟环境
pip 的配置文件位于相当标准的位置,并且这个位置在不同的操作系统上是不同的,利用 pip config
命令 -debug
选项可以进行查询:
1 | python -m pip config -debug |
1 | env_var: |
此外,环境变量 PIP_CONFIG_FILE
可用于指定首先加载的配置文件,其值将被上述文件中设置的值覆盖。将此值设置为 os.devnull
将禁用所有配置文件的加载。
当存在多个配置文件时,pip 会按照以下顺序组合它们:
PIP_CONFIG_FILE
(如果设置了的话)global
user
site
注意:每个文件读取都会覆盖从先前文件读取的任何值,即:site
配置文件的优先级是最高的
下面将展示几个配置文件的设置实例:
设置镜像源(index-url
)以及请求超时时间(timeout
)
1 | [global] |
或者让 pip 走代理(proxy
)
1 | [global] |
简单总结一下,关于 pip 配置文件设置的几个关键点:
- pip 配置文件格式:
ini
- 设置的名称源自长命令行选项,比如:
--index-url
- 每个子命令都可以在其自己的部分中进行选择性配置,并且将覆盖具有相同名称的全局设置
后记
对于掌握一个工具来说,除了了解这个工具的一些常用命令外,最重要的就是熟悉关于这个工具的配置文件:
- 知道配置文件在哪
- 如何对配置文件进行一些常规设置
- 设置日志文件的位置
知道配置文件在哪以及进行常规配置保证了工具能够按照自己想要的方式运行,设置日志文件的位置能够在工具运行出错时,知道去哪排查错误。
参考
pip documentation v23.1.2 : https://pip.pypa.io/en/stable/↩︎
还有一种比较常见的解释器
IPython
,用In [序号]:
作为提示符。比如:Anaconda 中的 Spyder↩︎通过
help(sys)
可以查询sys
模块的信息,该模块提供对某些对象的访问,比如:解释器使用或者维护的一些模块(sys.path
,sys.argv
和sys.modules
等等)以及和解释器进行强交互的一些函数(stdin
,stdout
和stderr
等等)↩︎Requirement Specifiers - pip documentation v23.1.2:https://pip.pypa.io/en/stable/reference/requirement-specifiers/#requirement-specifiers↩︎
Requirements File Format - pip documentation v23.1.2:https://pip.pypa.io/en/stable/reference/requirements-file-format/#requirements-file-format↩︎
事实上,Python 的包安装程序 pip 总是更喜欢 wheel,因为相比于 sdist ,wheel 安装总是更快:https://packaging.python.org/en/latest/overview/↩︎
Configuration - pip documentation v23.1.2:https://pip.pypa.io/en/stable/topics/configuration/#config-file↩︎