bigywater.tech
Python · 96

editable install:pip install -e 到底改变了什么

pip install -e . 让你改了代码立刻生效,不用每次重装。它到底改变了什么?这篇用两个后端——我自己写的最小 PEP 660 后端,和真实的 setuptools——各装一次,把 site-packages 里发生的事翻出来看。

一个 .pth 文件
可编辑安装在 site-packages 里留下的全部「代码」:一行路径
v1 → v2
改源码后可编辑安装立即生效;普通安装仍是旧版
脚本要重装
新增命令行入口不会自动出现,需要重新 pip install -e

验证一:普通安装是一份拷贝

实测 · 本机执行输出
  site-packages 里: ['hello_pkg', 'hello_pkg-0.1.0.dist-info']
  hello_pkg.__file__ = <工作目录>/envA/lib/python3.14/site-packages/hello_pkg/__init__.py
  改了项目里的源码(v1 → v2)之后, 新进程里 hello_pkg.VERSION_TEXT = v1  ← 仍是旧的

装完之后 hello_pkg 是 site-packages 里的一个目录,__file__ 指向它。这时候去改项目里的源码,新进程里 import 到的还是旧代码——需要重新 pip install。

验证二:可编辑安装留下的只有一个 .pth

实测 · 本机执行输出
  pip install -e ./projA → 返回码 0 | Successfully installed hello-pkg-0.1.0
  site-packages 里: ['__editable__.hello_pkg.pth', 'hello_pkg-0.1.0.dist-info']
   __editable__.hello_pkg.pth 的内容: <工作目录>/projA/src
  hello_pkg.__file__ = <工作目录>/projA/src/hello_pkg/__init__.py
  sys.path 里有项目的 src 目录? True
  dist-info/direct_url.json = {"dir_info": {"editable": true}, "url": "file://<工作目录>/projA"}
  改源码(v1 → v2)之后, 新进程里 VERSION_TEXT = v2 (改过源码)  ← 立刻生效, 没有重新安装
  在 src 下新增一个包 newpkg 之后, 直接 import newpkg → 成功 1

site-packages 里没有任何代码:只有 __editable__.hello_pkg.pth 和一个 dist-info。.pth 里就一行——项目 src 目录的路径,解释器启动处理 site 时(第 86 篇)把它加进 sys.path,于是 import hello_pkg 直接读项目目录里的文件。direct_url.json 里的 "editable": true 是 pip 记下的「这是可编辑安装」标记。改源码后立刻生效,src 下新增的包也能直接 import,因为整个目录都在路径里。

说明:这里的 .pth 做法是我自己的最小后端选择的实现(PEP 660 只规定接口,怎么做由后端决定)。下面用 setuptools 验证它是不是普遍做法。

验证三:哪些东西不会随源码自动更新

实测 · 本机执行输出
  往 pyproject.toml 里新增脚本 hello-two 之后, env/bin/ 里: ['hello-one']
  重新 pip install -e 之后: ['hello-one', 'hello-two']

命令行脚本是 pip 在安装时根据元数据生成的(第 95 篇)。往 pyproject.toml 里新增一个脚本 hello-two,env/bin/ 里并没有它,直到再执行一次 pip install -e。同理,依赖、版本号这些元数据变了也需要重装。

验证四:真实的 setuptools 也是这样吗

实测 · 本机执行输出
  pip install -e ./projS(setuptools)→ 返回码 0 | Successfully installed hello-pkg-0.1.0
  site-packages 里: ['__editable__.hello_pkg-0.1.0.pth', 'hello_pkg-0.1.0.dist-info']
   __editable__.hello_pkg-0.1.0.pth 的内容: <工作目录>/projS/src
  hello_pkg.__file__ = <工作目录>/projS/src/hello_pkg/__init__.py
  setuptools 版:在 src 下新增包 newpkg 之后 import newpkg → 成功

在 src 布局下,setuptools 生成的同样是一个 __editable__.hello_pkg-0.1.0.pth,内容是项目 src 目录,新增的包也能 import。这只是 src 布局下的结果:我没有验证平铺布局或多个顶层包的情形,不同布局下 setuptools 可能采用别的策略,别把这次结果当成所有情况。

验证五:卸载

实测 · 本机执行输出
  卸载可编辑安装后, site-packages 里: [] | 项目源码还在吗? True

卸载可编辑安装只删除 .pth 和 dist-info,项目源码原封不动。

分步演示:同一次改动,普通安装与可编辑安装的差别

所有内容取自上面的真实输出
pip install -e 到底做了什么
当前观察

    本文用到的工具与边界

    • 本机 macOS 27 / Python 3.14.7,pip 26.2.1,setuptools(pip 隔离环境按需下载的当前版本);第一个后端是自己写的最小实现
    • 没有验证:setuptools 在平铺布局 / 多包布局下的策略(可能不是 .pth)、hatchling 等其他后端、--config-settings editable_mode=strict、编译型扩展的可编辑安装
    京ICP备2026067502号-1京公网安备11010502063487号