npm 和 pip 分别是如何解决包依赖冲突的
npm
对于 npm v2,npm install
时每个包都会在各自的 node_modules
文件夹中存放自己的依赖。这样对于一个稍大型的工程,会有成千上万的文件存在。
npm v3 把依赖库尽量地 flatten 到顶级 node_modules
中,但是版本有冲突的情况下,还是使用 v2 的行为。不过这样已经解决很大一部分问题了。(来源)
目录结构
对于非 global 方式安装的包,包本身代码和它的依赖是在同一层目录:
$ mkdir test-dir && cd test-dir
$ npm install http-server
$ ls node_modules
async colors corser ecstatic eventemitter3 he http-proxy http-server mime minimist mkdirp opener optimist portfinder qs requires-port union url-join wordwrap
对于 global 方式,包的依赖放在它本身的 node_modules
里面,而不是在同一层目录。比如对于 http-server 这个包,它的依赖放在 /usr/lib/node_modules/http-server/node_modules
里面。
无论是哪种方式,npm remove
一个包时都能正确地处理依赖:
- 全局方式时,删除该包的最上层目录,如
/usr/lib/node_modules/http-server/node_modules
- 非全局方式时,npm 会去读
package.json
文件,判断要删除的包有哪些依赖还被别的包依赖着,这些包不会被删除
pip
pip 并 没有 真正的 dependency resolver
,你可以在 requirements.txt
文件中强制指定依赖库的版本,这会覆盖掉各个库在 setup.py
中指定的版本。
目录结构
pip 安装的包,跟它的依赖最终都会放在同一层目录平躺着。
pip 安装包时是装到一个 env(一般是全局 env / vitualenv),而 npm 装包是针对全局 / 一个项目的。这导致 npm 处理依赖时更为灵活、合理,因为它没有多个项目共享同一套包。所以 pip remove 一个包时,并不会同时删除它的依赖。
Python 的打包感觉太复杂,存在 distutils
, setuptools
这两个让我搞不清楚的库,打包格式又有什么 source distribution, egg, wheel 等奇奇怪怪的东西。有必要的时候再研究了。
感觉 npm v3 的解决办法是最好的。