前言
「库安装与使用」这个说法里藏着两个容易混淆的概念。第一,Python 的「库」分成两类:标准库(standard library)随解释器一起装好,import就能用;第三方库(third-party package)要自己下。第二,「安装」这个词只对第二类成立——你没办法「安装」json或者datetime,它们本来就躺在那里。很多人第一次遇到ModuleNotFoundError时,第一反应是「我是不是没装 Python」,其实只是把一个第三方包当成了标准库。
还有一个高频误解:pip install装的东西放进了哪个环境?如果你在同一台机器上有多个解释器、多个虚拟环境,装错位置是家常便饭,症状是「刚才明明装了,怎么又找不到了」。
本文先把模块、包、库三个词的层级关系理清,再讲pip的完整用法,然后给出几个只用标准库就能跑通的使用示例,最后说明第三方库该怎么稳妥地引入。Python 2.7 已于 2020 年 1 月 1 日停止维护,本文所有写法都是 Python 3 的。
一、模块、包、库:先把层级理清
| 名词 | 英文 | 是什么 | 例子 |
|---|
| 模块 | module | 一个.py文件 | json.py |
| 包 | package | 含__init__.py的目录(命名空间包可省) | email目录 |
| 库 / 发行包 | library / distribution | 可被pip安装的一个发布单元 | pip装的一个包 |
| 标准库 | standard library | 随解释器发布的一整套模块 | json、os、socket |
| 第三方库 | third-party | 别人发布、需要单独安装 | 见第四节 |
import语句找的是模块,pip装的是发行包。一个发行包里可能包含多个模块和子包,所以「发行包名」和「import 时写的名字」并不总是一致——这是第四节要专门提醒的地方。
# 适用于 Python 3.8+
import json
from collections import Counter
from pathlib import Path
print(json.dumps({"a": 1})) # {"a": 1}
print(Counter("aabbc").most_common(1))
print(Path(".").resolve().name)这三行能跑,是因为json、collections、pathlib都是标准库,不需要装任何东西。
二、pip 的完整用法
官方的安装方式推荐python -m pip,这样能确保 pip 和解释器是配套的。
# 需要 Python 3.4+(pip 随解释器附带);在虚拟环境里执行
python -m pip --version # 确认 pip 属于哪个解释器
python -m pip install 包名 # 安装最新版
python -m pip install "包名==1.2.3" # 安装指定版本
python -m pip install --upgrade 包名 # 升级
python -m pip uninstall 包名 # 卸载
python -m pip list # 列出已安装的包
python -m pip show 包名 # 看版本、依赖、安装位置
python -m pip freeze > requirements.txt # 导出当前环境的依赖清单
python -m pip install -r requirements.txt # 按清单安装几个实用细节:
pip show的 Location 字段是排查「装到哪去了」最直接的证据。如果它显示的路径不属于你正在用的解释器,那就装错地方了。- 版本约束写在参数里,
==精确匹配、>=下限、~=兼容匹配。约束写法要加引号,避免被 shell 当成重定向符号解释。 - 离线或内网环境可以用
--no-index --find-links指向本地的包目录。
三、标准库使用示例
示例一:JSON 读写
# 适用于 Python 3.8+
import json
data = {"name": "示例", "values": [1, 2, 3], "ok": True}
text = json.dumps(data, ensure_ascii=False, indent=2)
print(text)
restored = json.loads(text)
print(restored["values"][1]) # 2
print(type(restored["ok"])) # <class 'bool'>ensure_ascii=False让非 ASCII 字符按原样输出而不是转成转义序列,处理中文时几乎必加。indent只是排版参数,不影响语义。
示例二:计数与排序
# 适用于 Python 3.8+
from collections import Counter
words = "the quick brown fox jumps over the lazy dog the fox".split()
c = Counter(words)
print(c["the"]) # 2
print(c.most_common(2)) # 出现次数最多的两项
print(sorted(c)) # 按词本身排序的键列表Counter是dict的子类,取值时即使键不存在也返回0而不是抛KeyError,这是它和普通字典最容易察觉的区别。
示例三:路径与文件
# 适用于 Python 3.8+
from pathlib import Path
base = Path("demo")
base.mkdir(exist_ok=True)
target = base / "note.txt"
target.write_text("第一行\n第二行\n", encoding="utf-8")
print(target.read_text(encoding="utf-8").splitlines())
print(target.suffix, target.stem, target.parent.name)pathlib用/运算符拼路径,比字符串拼接更可读;显式写encoding="utf-8"能避免不同平台默认编码不一致造成的乱码。
示例四:日期与时间
# 适用于 Python 3.8+
from datetime import datetime, timedelta
now = datetime.now()
print(now.isoformat(timespec="seconds"))
later = now + timedelta(days=7)
print((later - now).days) # 7datetime是不可变的,now + timedelta(...)返回新对象,原对象不变——这一点和列表的+=完全是两回事。
四、第三方库怎么引入
第三方库的通用流程是:先装,再import。装之前建议先pip show 包名看是否已经存在,避免重复安装。
# 需要 Python 3.4+;示例流程
python -m pip show 包名 || python -m pip install 包名
python -c "import 包名; print(包名.__version__)"import 之后用print(模块.__version__)确认版本是常见做法,但要注意并非所有包都提供__version__属性,没有的时候这条命令会抛AttributeError,改用python -m pip show 包名看版本更可靠。
第三方库的具体函数名、参数名和返回类型,请一律以该库的官方文档为准。本文不列出任何未经核对的第三方 API——网络上有大量复制粘贴的示例代码,参数名早就随着版本改掉了,照抄很容易踩坑。
选库时看三个信号:官方文档是否完整、最近一次发布距今多久、是否声明了支持的 Python 版本范围。最后一个尤其重要,装一个只支持到 3.7 的库到 3.12 环境里,装得上不代表跑得动。
五、依赖清单与复现
requirements.txt是跨环境复现的标准做法。
# requirements.txt 的常见形态
# 直接依赖,允许小版本浮动
requests>=2.28
# 精确锁定
flask==2.3.2
# 从本地目录安装
./local_package# 需要 Python 3.4+
python -m venv .venv
source .venv/bin/activate # Windows 用 .venv\Scripts\activate
python -m pip install -r requirements.txt
python -m pip freeze > locked.txt # 生成带精确版本的锁定清单区分两份清单很实用:requirements.txt写你直接依赖的东西,允许合理浮动;locked.txt由freeze生成,包含全部传递依赖的精确版本,用于生产环境复现。
常见坑点
- 把第三方包当成标准库
❌ 直接import 某个第三方包,报ModuleNotFoundError,然后去重装 Python。
✅ 先分清标准库和第三方库。标准库不需要装;第三方的要用python -m pip install 包名装当前这个环境里。
- 用
pip而不是python -m pip
❌ 机器上有多个解释器,pip install装到了 A,python跑的是 B,于是「装了却 import 不到」。
✅ 用python -m pip install,并用python -m pip show 包名的 Location 字段核对安装位置。
- 忘记激活虚拟环境
❌ 在全局环境里装了一堆包,项目间版本互相打架。
✅ 每个项目一个 venv,装包前确认命令提示符前面有环境名,或者用环境内解释器的绝对路径。
- 发行包名和 import 名不一样
❌ 以为pip install的名字就是import的名字。
✅ 两者可能不同。装完用python -c "import 实际模块名"验证一次,具体以该库文档为准。
pip freeze当成依赖声明用
❌ 把freeze出来的上百行清单直接当项目依赖文件,里面混进了只在开发机上存在的包。
✅freeze用于锁定复现;声明依赖手写,只列直接依赖。
- 版本约束不加引号
❌ 写pip install 包名>=1.0,>被 shell 当成重定向,报奇怪的错误。
✅ 加引号:python -m pip install "包名>=1.0"。
import之后用__version__判断版本
❌ 用模块.__version__判断版本,遇到不提供该属性的包直接抛AttributeError。
✅ 用python -m pip show 包名看版本,它对所有包都有效。
- 用
pip install --user却搞混了用户目录
❌ 全局和用户目录里各有一份同名包,import 到哪一份取决于sys.path顺序,非常难排查。
✅ 尽量用虚拟环境隔离;发现异常先用python -c "import 模块; print(模块.__file__)"定位实际加载的是哪一份。
总结
| 需求 | 命令 / 写法 |
|---|
| 看装了没有 | python -m pip show 包名 |
| 安装 | python -m pip install 包名 |
| 装到指定环境 | 先激活 venv 再执行上面两条 |
| 确认 import 到哪个文件 | python -c "import 模块; print(模块.__file__)" |
| 导出 / 还原 | python -m pip freeze/python -m pip install -r |
标准库优先、第三方按需装、每装一个都确认它落进了哪个环境——这三条落实了,「库安装与使用」就不再是玄学。第三方库的 API 细节永远以官方文档为准,别信二手代码片段。