python pip
# 聊聊Python生态里那个被用烂了的工具pip前些天跟一个刚入行的朋友聊天他说自己装了Python之后第一步就是装了个Anaconda因为“网上都这么说”。我问为什么不用pip他愣了一下说“那个不是装库的吗”这话乍一听没错但仔细琢磨就好像说“冰箱不是用来保鲜的吗”一样——对但只说对了一小半。pip是什么pip的全称是“Pip Installs Packages”一个递归缩写很有点程序员式的幽默。它是Python官方推荐的包管理工具从Python 3.4开始就随解释器一起打包。本质上它就是个命令行程序专门负责从PyPIPython Package Index全球最大的Python包仓库下载和安装第三方库。有意思的是很多人天天用pip install却不知道它到底在干什么。其实整个过程可以简化成三步解析依赖关系、下载wheel或源码包、解压并放置到site-packages目录。如果你是源码安装还要负责编译。这些东西对日常使用者来说都是透明的但这种“透明”有时候也会带来麻烦后面再聊。它到底能做什么如果只回答“安装包”那就像说手机只能打电话。pip能做到的事情远比这个多安装单个包当然是最基本的。但如果你在团队协作中会发现pip结合requirements.txt文件的价值。所谓requirements.txt就是一个文本文件列着你项目依赖的所有包及其版本。团队里的新人拉下代码后一条pip install -r requirements.txt就能复刻出一模一样的开发环境。这个东西我在无数个项目里见过但大部分团队都写成了“xx1.0.0”这种宽泛的版本——说实话这种写法跟没写区别不大后面再说。pip还能帮你管理已经安装的包。pip list列出所有包pip show查看某个包的详细信息包括它依赖了什么、安装在了哪里。开发中遇到“奇怪报错”时我经常先跑pip list看一眼往往能找到问题根源比如某个库的版本跟其他库冲突了。还有一个不太被人注意的功能是pip download。它只下载包但不安装这在离线环境或者需要手动审查包代码时非常有用。以前做过一些安全检查严格的客户项目所有的依赖包都要求先下载下来人工过一遍再拿到内网安装这个功能帮了不少忙。怎么用才顺手安装包最常见的是pip install requests但大部分人不知道可以加上--no-cache-dir这个参数。有时候你遇到“明明装了新版却还是旧版行为”的问题很可能是因为pip从缓存中拿了个旧版本。加上--no-cache-dir强制全量下载能解决很多莫名其妙的问题。升级包是pip install --upgrade但pip install -U是简写一样。卸载是pip uninstall。这里有件趣事见过有人写了个脚本反复装包卸载包测试环境搞得很乱——其实可以用pip freeze requirements.txt备份当前环境状态出了问题直接用pip install -r requirements.txt --force-reinstall一键还原。对于虚拟环境的支持pip配合venv模块最常用。创建环境python -m venv myenv激活后pip就装在这个环境里了互不干扰。很多人不知道python -m pip和直接pip的区别——前者保证你用当前环境对应的解释器后者可能有路径冲突。我习惯写python -m pip少很多“明明装了却说没有”的问题。真正可能在实战中帮到你的东西版本锁定是个常见陷阱。写requirements.txt的时候最好用1.0.0这种固定版本而不是1.0.0。如果你说“我是为了兼容性”那更应该锁死——因为你不知道上游库的新版本会引入什么破坏性变更。实际经历有个微服务因为某个库从1.2.3升到1.2.4内部改了某个函数的默认值导致线上数据异常。从那以后但凡生产项目我都会在requirements.txt里锁死版本号。另一个容易被忽视的是--find-links参数。它允许你指定一个本地目录或私有仓库作为包的来源。在大公司工作过就知道很多情况不能直接连外网。可以在公司内部建个PyPI镜像或者索性把包都整理到一个共享文件夹用pip install --find-links /shared/packages requests从本地安装。速度比从仓库下载还快。还有个小技巧pip config可以改写配置文件。比如设置超时时间或者默认使用镜像源可以写一行pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple以后就不用每次输-i参数了。换几个别的看看聊pip肯定绕不开conda。conda是Anaconda和Miniconda自带的包管理器它不仅能管Python包还能管系统级的二进制依赖比如CUDA、OpenCV这类。如果你做数据分析、机器学习conda确实省心因为很多数学库在pip上装可能会遇到编译问题conda作者已经帮你编译好了。但conda有两个问题一是仓库不如PyPI全一些较新或者不那么主流的包只有PyPI有二是它的环境管理相对独立跟系统pip混用容易出问题。我一般建议普通Web开发或者脚本项目用pipvenv而处理数据科学相关时可以考虑conda。还有poetry和pipenv。poetry的出现是解决依赖管理更精细化的问题它会检查整个依赖树确保没有冲突。但说实话对于大多数中小型项目来说足够仔细地写requirements.txt加上定期更新效果没有本质差别。pipenv把包管理和虚拟环境合了但个人使用体验里感觉有点过重而且锁文件机制在一些场景下反而增加了复杂度。用pip这么多年它最让我欣赏的地方就是简单。简单到几乎没有学习成本简单到习惯了就忘了它的存在。无论后来出了多少花哨的工具pip始终是自己最常碰到的选择——可能不是最好的但够用而且可靠。