Python的包管理感觉怎么这么不优雅?
本人前端一枚,习惯了 node 的 npm 之后感觉配置和使用起来都很简单方便,最近学习了一点 python 后,感觉 python 的包管理怎么这么不优雅。首先,配置文件居然是用 txt 文件来写的,二进制文件我用编辑器是无法打开的,然后用 git 也不能很好的版本管理;其次,pip install 是把包全都装在了全局,打开用户目录,一大堆以点开头的文件夹,抓狂。。。
Python的包管理感觉怎么这么不优雅?
Python 的打包确实是比较复杂,你可以看看这个 template: https://github.com/kennethreitz/setup.py
但是你后面的结论就不对了:
> 配置文件居然是用 txt 文件来写的
不知道什么意思……文件要么二进制文件要么文本文件,txt 是什么?
> 二进制文件我用编辑器是无法打开的
这是你编辑器的问题。况且你为什么要用编辑器打开二进制文件?你期望看到什么?
> 然后用 git 也不能很好的版本管理
我假设你说的是管理依赖?一般写到 requirements.txt 里面,手动写更容易控制版本和依赖。
> pip install 是把包全都装在了全局
用 virtualenv,python 的环境可以非常干净的
> 打开用户目录,一大堆以点开头的文件夹
你说的点开头的文件是什么?就算装到系统里面,也是在 site-package 里面。
------
最后多说一句,少抱怨,多去 Stack Overflow 找找解决方案。我向你保证 Python 的依赖可以处理地很干净的。比起 JavaScript 来坑少很多了。
贴点资料: https://www.kawabangga.com/how-to-learn-python
Python的包管理确实有槽点,但也没那么糟。pip+virtualenv是标准组合,用熟了其实挺顺手。conda在数据科学领域很流行,环境隔离做得不错。Pipenv和Poetry这些新工具在解决依赖解析和锁定方面有改进,但生态和稳定性还需要时间。关键是根据项目需求选对工具,别盲目追新。
你怕不是没遇到过这种情况咯。
JavaScript 莫名奇妙不工作,然后把 nodule_modules 文件夹删了,然后再 yarn 一下就可以了。 依赖库完全没改变。 神奇吧。
为啥要 pip 安装?能不 pip 就不 pip 啊,安装源里的多好
什么二进制文件需要用编辑器编辑还得用 git 管理……
node 和 python 半斤八两,开源的项目都是一堆 issue 都是跑不起来的,全死在版本上
Do one thing, do it well. 这是 unix 的哲学,是传统,pipenv, pyenv 啥的还算好用
npm 那种啥都能干的工具才是异端
很多 linux 新手跟我抱怨 Linux 真难用,那是因为他们爸 Linux 当 windows 用。你那 pip 当 npm 用,自然要吃瘪
一堆点开头说明你用的是 Windows 吧,手动隐藏就好了啊。
不用 pip 用啥?
现在自带 venv 了 还算高级。
多看说明书,都有最佳操作的。
Python 的包管理很科学,npm 的包管理才是非常不科学。
即便这样,我在 ArchLinux 上还是用 pacman 来装 Python 包,这样就能随着系统更新而滚动更新。官方源+archlinuxcn 源+AUR 覆盖了我大部分需要的包,剩下的用 pip install --user 来安装。
至于 virtual env 的话,也只适合在开发环境用,针对特定项目使用,日常使用并不需要那么搞得复杂。如果你在对付一个老项目并且有大量的坑填不过来,那么就用它来维持一些旧版本的库吧,否则的话还是建议把所有的库更新到最新。
我使用 Archlinux,其中一个原因也是他们把所有包都更新到最新,避免了我以前使用 debian/fedora 的那种 Dependency hell,摆脱了大量为了照顾老项目而影响体验的历史遗留问题。
与此同时,npm 的依赖版本写死不更新却成为一种共识,有点可悲。
conda 一次安装 基本都够用了。
蛤蛤 npm 居然嘲笑 pip 🙈
pip 已经挺好了……
当然在一些依赖传递时可能会有一些冲突,不过没碰到过
你让 go 怎么活?官方软件包管理工具的难产……
python 的包管理就不要洗了,公认的很糟糕了。要是涉及到 numpy 之类 cbinding,打包那可是各种 hack。
不管 npm 还是 yarn 都比 pip 强,deploy 的话有个 Dockerfile 和 npm i 就不会出问题; python 就看运气了,即便 docker、conda/venv 用上了还会有幺蛾子。
之前 deploy 一个 ML 的 service,必须把 numpy 从 requirements.txt 里拉出来单独跑一遍 pip install 才行,逗我。
至少比 npm 问题少多了,npm 是真的迷。(怨气满满的说道。
#3 多么痛的领悟啊,我就经常这么干
你需要 pipenv
经常遇到,也是这么解决的。
pipenv 算是比较新的比较先进的。每个项目会有依赖列表文件,依赖安装的位置也是确定的
bundler 路过
听你们说 pip 很坑的样子,可能是我用了个假的 pip 吧
pip 是不考虑安装环境的,如果你要安装的库里面需要系统环境支持的话,就需要自己把环境配好。
比如 lxmlx,就是个大魔王,网上搜下,多少人躺过这个坑。
如果不涉及 C 库或者系统环境还好,不然还真的蛮头疼的。
所以 conda 就是为了解决这个的,真的很好用,安装包的时候,顺带帮你把这个包所需的环境包也装了。
windows 下面 pip 的确蛮烦的
遇到过,热更新总是延时,也是这样解决的。
对于 Python 库,可以用 pipenv,最新的最佳实践。
如果是带 C 扩展的 Python 库(比如 mysqlclient ),会麻烦一点,需要保证你的系统环境上有相应的 C 库(如 libmysqlclient.so )。这块可以看下 Anaconda 的实现。
pip 的确比 npm 设计上差老多了。
但是因为 python 不像 js 包分的很细很多,py 项目总的包数量是很少的,所以还能处理。如果 py 也像 js 几行代码都能做一个包,那他这个设计早就崩溃了。
所以,有了 pipenv 啊
我用 python 写爬虫的时候也是这样想的,不过后来用了 golang。。。。
pip 和 npm 都挺难用的
Linux ? 装软件软件源里的,几乎都有。没有的自己打包个。
遇到过。
…
virtualenv
用了 golang 的包管理 你就会觉得 pip 是多么优秀了 www
带 C 拓展的确实很复杂,尤其是 Linux,不同系统依赖的动态链接库不一致,在脚步语言里是硬伤,npm 也有类似的问题,只不过它很少带 C 拓展的库。docker 按理说不会有这种问题。
npm 五十步笑百步啊。。。。。pip 确实不优雅,npm 简直了。。。。。
npm 居然敢说 pip ?
npm 能嘲笑的大概只有 go 和 C++了吧?
python10 年前的代码,今天还能用。
nodejs10 个月前的代码,今天怎么用?
感谢感谢,早上起来一看感觉自己无脑发的帖子好傻逼😭😭
学的姿势不对啊
一般教程不都是教你先安装一个虚拟环境的么 这样可以避免包的混乱和版本冲突
所以楼主可以在发个帖子控诉下辣椒编辑器 atom 把 txt 文件识别成二进制文件⊙∀⊙?
优雅?知乎看多了?
没有任何嘲讽的意思哈,但是网上评价好像 npm 比 pip 要挫一点把
前一阵子不是还有个 nodejs 开发者 删了自己的库,那个库是字符串处理的,
导致几十个 几百个知名的库都不能用的问题吗
楼上的嘲讽都没什么意思
我理解楼主说的 txt 应该是指相对于 npm 用 json 这种有格式的配置 为何 pip 要用 txt 这种没格式的
首先 pip 的 txt 其实也是有微格式的 只是你可能没用到 只是看到名字罗列而已
其次 基于行文本是个 unix 传统 可能 pip 的作者比较欣赏这种 又或者只是遵循了周围的惯例
最后 安装到全局这个确实不如 npm 方便 但是 npm 出来前 大家都是默认这么干 也没什么好说的 可以去推动他改 至于说用户目录下一堆点开头的目录 这又是一个 unix 传统 :D
PS 感觉现在社区总是嘲讽多 回答少 不如从前了
那么 npm 的 cbinding 怎么处理?
我觉得 txt 没毛病啊
#16 golang 的包管理真的差
其实大多数包,在 archlinux 下用 pacman 或者 AUR 装,都自动处理好了 C 库的依赖。
装 python-lxml 的时候,会自动安装依赖 libxslt,装 python-scipy 会自动安装 scipy。
关于包的列表,以行来分割有很大的方便性。sed、grep、xarg、cut 等等的工具都是以行为单位处理的。
我就是通过 pip freeze > pip_package_list 来备份包列表,同时把列表放在 dotfiles 里面的。
我最近尝试在我的 dotfiles 下加一个 Dockerfile,通过 docker 来让我的服务器保持跟我桌面一样的环境(装相同的软件,相同的 zsh、vim 配置)。
我在 Dockerfile 里的其中一个操作就是 pip install -r <(cut -d = -f 1 pip_package_list) --user,通过 cut 命令来把版本号截掉,从而让 pip 安装最新版本。
npm install 一次都能下班了,我说什么了吗?
不同意您的回答
> 我假设你说的是管理依赖?一般写到 requirements.txt 里面,手动写更容易控制版本和依赖。
实在不知道您是如何得出这个结论的。依赖是 nested 的。也就是有依赖的依赖的依赖。你不用软件来记录这些 nested dependencies,最后的结果就是 inderterministic build.
Pip 最大的问题是其缺乏重现能力… npm 的 package.json 和 npm install 虽然繁琐并且一个小小的项目就会用到几百兆的硬盘,但是其有极好的重现能力。也就是说,给你一个 package.json 和项目源码,你是可以重新跑这个项目的。
而 pip 的重现能力就令人质疑了。如果您随便去 github 找个 jupyter notebook,只要它用了一些小众的 library 像 websocket, aiohttp 之类的,很有可能那个 notebook 会跑出错误,因为 ipynb 并不记录其依赖的包。
在写过一段时间 npm 的代码后,我又重新写回了 python 代码,又出现一些奇奇怪怪的错误,然后我去 google 查这个错误,发现是某个包的版本错误了,然后我用 pip 来更新这个包,最后解决了这个 bug。但是我不应该要操心这种 bug。pip 应该帮我记录所有的依赖。
然而 pip 做依赖有各种各样的问题,有兴趣的可以看看这篇文章 https://medium.com/alonisser/things-i-wish-pip-learned-from-npm-f712fa26f5bc?source=linkShare-c6ac3e2e940f-1515034677
其中提到很有意思的一个事情,也就是 python 不允许一个 library 存在两个版本。但假如说你有两个包,包 A 依赖包 [email protected],包 B 依赖包 [email protected]。你用 pip 装完 A 和 B,你会发现包 C 是版本 1.1 或者 1.2 (看你安装的顺序)。但是实际这种情况经常发生,发生的时候你只能祈祷包 C 没做什么大的改动,所以代码还可以跑,但这毕竟还是显示了 python/pip 重现能力有很大问题。
有些人提到了 python 有 pipenv。这个项目确实不错,但是实际用起来好像还是有各种问题。我用过一次,但是装了一些依赖后又出现一些奇怪的错误,似乎和 C-extension python 包有关系,总之用得不像 npm 那样畅快。
看到大多数人都说 pip 比 npm 好,我觉得可以理解(因为你不用为每一个项目繁琐地装几百兆依赖),但是我认为这种看法是不深刻的。
我是很喜欢 python 的,但是每每想到这个问题就觉得很难受。觉得自己写的代码无法保证在别人电脑上也可以 deterministically 跑。也许某天某些包升级了,我的代码就失效了,这实在是让人担忧和痛心的事。
希望大家理性看待。

好黑!!
经常会看到 node-gyp,不管是安装或者定义依赖用户都不需要做额外的事情。
有些包还是会在全局写文件。。即便用了 venv。
你颠覆了我对二进制文件的理解……
> 实在不知道您是如何得出这个结论的。依赖是 nested 的。也就是有依赖的依赖的依赖。你不用软件来记录这些 nested dependencies,最后的结果就是 inderterministic build.
你说的软件记录指的是 pip freeze > requirements.txt 吗? 这样的确可以将所有包的版本准确导出。但是并不是推荐的做法。加入你只依赖了 requests,自动导出会将 requests 依赖的库(当前 pip 所有的依赖)都导出。你自己看到这个文件,都不知道哪些是项目依赖的,哪些是 requests 依赖的了。
我的观点是,Python 的 requirements.txt 应该是可读的。如果你的项目依赖了除标准库的 requests,那么就在文件里面写 requrests (指定最小版本或者不指定),requests 的依赖交给 requests 去搞定。这样不好吗?
pip npm go 都不行( C++有包管理?)
求推荐一个包管理做的好的语言入坑?
> 其中提到很有意思的一个事情,也就是 python 不允许一个 library 存在两个版本。但假如说你有两个包,包 A 依赖包 [email protected],包 B 依赖包 [email protected]。你用 pip 装完 A 和 B,你会发现包 C 是版本 1.1 或者 1.2 (看你安装的顺序)。
发生这种事情本来就是不科学的,不过我还没遇到过。好像 pipenv 在解决这个问题。
我还是坚持我的观点,如果用 requirements.txt 写依赖的话,应该是人工维护,可读,不写依赖的依赖。比如这个:
https://github.com/getsentry/sentry/blob/master/requirements-base.txt
这样不好… 我都不知道小型的项目要怎么手写这个
requirements.txt 。难道挑几个自己 import 的包写吗…?那万一漏一个怎么办,万一你选的这几个包依赖的包版本有冲突怎么办?
漂亮
感觉 npm 比 pip 来得好用,虽然下载的依赖大一点,多一点,不过部署起来挺方便,说 node_modules 目录嵌套深的,那已经是以前的事了,npm install 换淘宝源也不慢,现在 npm 的安装速度和 yarn 也差不多了
npm 把 pip 吊起来打,实际使用问题多无非是因为 js 包很多,更新快,而且还支持多个版本共存。pip 要是处理这种情况,早完犊子了
不会玩 Virtualenv 么? 直接把整个环境打包移到目标环境就行了. 最笨的办法 pip download 包在本地目录.
pipenv 还好吧,另外 npm 嵌套路径过深的问题应该解决了吧已经…
用到了什么外部依赖就写什么呀,自己依赖的什么必须要清楚啊,总不能稀里糊涂把当前的环境的依赖都生成进去吧。既然是小型项目,那还要有多少外部依赖?
怎么可能漏?
基本不会冲突(我没遇到过),因为大家一般都是规定最低版本。如果真有两个包最高版本冲突,那说明其中有一个包太久不更新或者本身就存在问题,具体解决吧。
10 年前的 Python 现在还能用你怕是在做梦,Python 是两种语言的梗是怎么来的都忘了?
另外上面居然又这么多人支持 pip 觉得没问题我真的是很好奇都是只写过 Python 没写过其他语言吗?
已经有人指出了一个场景,就是不同依赖依赖了某一个包的不同版本。 我同意你的看法版本冲突的时候是存在问题,并且这种问题一般无法自动解决。但这种情况不应该报错终止吗?而不是默默的根据安装顺序去决定
依赖文件放在全局而非项目里这个上面已经有人提供解决方案了。
另外就是各种系统 /环境依赖相关的依赖,比如各种需要自己去编译 C 源码的依赖都是坑。
反正 Python 的项目我见到能够拿到手直接 pip install -r 然后就能成功安装依赖并跑起来的项目真的是太少太少了_(:з」∠)_
没感觉到难用啊
> 发生这种事情本来就是不科学的,不过我还没遇到过。好像 pipenv 在解决这个问题。
恰恰相反,这种情况每时每刻都在发生。只是因为您们没有意识到而已。您写个项目,总得用些包吧?而您的包是有个固定版本的。假设您 1 月份装 anaconda,我 3 月份装 anaconda,很有可能我们的 pandas 版本不同。
我举一个很简单粗暴的例子来和您展示 python/pip 的包管理能有多么的糟糕。假如说您写了一个包,里面有代码print(df.iloc[2])( df 是 pandas.DataFrame 对象);再假设你的 pandas 版本为 1.0 ;然后假设我写了个包,里面有代码print(df.indexloc[2]);假设我的 pandas 版本为 1.1,并且在该版本中重新命名 DataFrame.iloc 为 DataFrame.indexloc。
那么这时候,如果一个人做另外一个项目用了我们的 dependency,他基本上是陷入了绝境。python 不允许一个包有多个版本同时存在。也就是说,如果他后 pip install 你的包,pandas 版本就是 1.0,这时候程序报错:indexloc undefined,因为我的包用了 pandas 新 api indexloc。那如果他后安装我的包,那么 pandas 版本为 1.1,这时候程序也报错:iloc undefined,因为他用了已经过时的 api iloc。
也就是说,你陷入了必定 bug 的局面。现在 python 没有好的办法可以解决这种问题。唯一的方式是:把 pandas 1.0 拷贝然后改名称 pandas_dummy,修改其中相关的代码( absolute import 可能会出问题),然后在你的包里写 import pandas_dummy as pandas.
虽然我用的是一个 dummy example,但是你可以想象得到,在当今项目依赖成百上千的包并且这些包在不同变化的前提下,这种情况应该是时有发生的。所以大多数包 depreciate api 的时候才会告诉你他们再过几个版本会 depreciate,也许这样会给你一些缓冲的版本来解决这种依赖冲突。
但是简单来说,你的程序没有重现的绝对保障。换句话来说,你的程序能不能跑有些看运气。
virtualenv 和 pipenv 都没有解决 dependencies collision。请看我刚刚写的例子。
你太依赖“每个依赖包版本必须精确到 minor version ”这个事实了。Python 社区的 major version 兼容性和 depreciate api 是好事,JS 那种根本不敢升级依赖包版本的才是耍流氓。开源软件包修个小 bug 是常见的事情,Python 升级依赖包版本我基本都是无脑做的,npm 你升级依赖包版本哪次不是胆战心惊。
Python 社区有很多“约定俗成”,你得习惯它们,并且享受它们。譬如 x.y.z,社区标准是保证 x. 不变程序就能跑,y 不变不会加入新功能。大家写程序也会考虑这个原则,如果不能,那么这个包大概是无法成为知名的包。
当然,特殊规定是,0.y.z 不考虑兼容性。直到 1.0.0 以后才有这个规定。所以你举得例子 pandas,不巧它才 0.20 。NumPy 已经 1.0 了,TensorFlow 也是,所以可以期待其兼容性。
另外我感觉我们说的似乎不是一个东西。我感觉您说的那个 requirement_base.txt 似乎更像是对项目的高阶描述:说的是我们主要的依赖是这些包,而我说的是 python/pip 缺乏重现能力。
> 基本不会冲突(我没遇到过),因为大家一般都是规定最低版本。如果真有两个包最高版本冲突,那说明其中有一个包太久不更新或者本身就存在问题,具体解决吧。
您的意思是似乎是说,出现了依赖冲突我们再想办法解决,而我是说,如果 pip 和 npm 一样,我们连这样的冲突都不会碰到,所以在这个角度上,pip 的设计是有缺陷和落后的。
另外您很少遇到不代表别人很少遇到,我 debug 这种依赖相关的 bug 应该不算少,总是要 pip uninstall,install,然后通过一番努力终于代码能跑。然而我厌倦了这种 debug,既然有 npm 这种一键解决你依赖问题的安装方式,为什么每次要自己找麻烦去手动解决依赖 bug 呢?
感同身受… 经常是 pip install 后出现一些奇怪的红字,然而无休无止无意义的依赖 debug 开始了
无论是 pip 还是 pipenv 都没解决依赖冲突,一个项目两个包依赖同一个包不同版本的情况。
,ipwx 您们说的约定俗成,向下兼容都是好的实践,但我说的重现能力…… 另外 js 未必就不能做你们说的最好实践。
所谓重现能力是我今天写的代码明天还能跑,而不是因为一些莫名其妙的原因不能跑了。和您们讲个自己的例子吧,我第一次写的小 /中型项目 https://github.com/streettraffic/streettraffic 用到了 websockets==3.3 这个依赖。我 setup.py 是乱写的,连版本号都没写,所以我写完几个月重装时发现跑不了了,后来 debug 之后发现是 websockets 高等版本破坏了原有的 api。
哪怕我在 install_requires 里面写了 websockets==3.3,只要别人在安装我的项目之后再安装一个项目有用到 websockets 的更高版本,我的代码就会报错了。
是的,我可以维护这个项目去修 bug,但是每个人的精力是有限的,并且你主要工作的项目也会变,所以我并不愿意改这个 api。我并不认为这样是错误的,并且我认为我写的代码如果能跑,便不应该因为这种依赖问题到后期某一天报错。
大哥,这问题明显需要升级来解决啊。包 1 和包 2 都是活跃的项目,基本不会有类似问题,人家肯定会做依赖升级啊。如果不是活跃的项目,手动 fork 一下,自己适配。所以啊,别用些没人用的包。。。给自己找麻烦。。。
又吵起来了哈哈,再怎么否认,python 的包管理对于项目开发就是一坨屎(作为系统工具还是可以的),各种 env 就是尝试把这坨屎的臭味盖起来。
感觉 PIP 真的是比 NPM 麻烦多了,比如环境的多版本,搞一堆方案,哪有带着依赖走爽。我现在也只用可以打包依赖的语言。
All right,你说的问题确实存在,但是 virtual env / anaconda env / docker 不是都能解决你的问题嘛?我觉得总有一款合适,所以不是什么大问题。
您这话说的。为什么不把 pip + virtual env / anaconda env 当做一个整体看,那样不就清静了么?还有 您说的这个需求,Anaconda 就支持。如果你更勤快点,Docker 也不错。总而言之您二位为什么就偏要把 pip 单独拿出来批判一番呢?
anyway,任何缺陷都是可以修正的,比如这几天的 CPU bug,只不过弥补缺陷的代价不一样。 docker 对于这些依赖问题确实可以解决,但也只是比较好看的“布”罢了。
#90 如果你能接受,没有人阻止你。再者我只表达意见,没有说服其他人的兴趣。
那些不是包管理工具,那些已经是用来给 pip 这么一个巨坑在那填坑的工具了
因为我最经常用 python 啊,但是想到以后写的代码会有这样重现问题就很头疼…
说白了就是 npm 支持多版本管理呗 。很难想象一个项目用那么包还要凑一起…要我们早就拆成不同服务了。我还是倾向单一版本管理… npm 用得我真的难受
现在 Pip 的问题是依赖,很多人直接 pip freeze > requirements.txt 简直想屎,没有依赖链很难受
说 npm 难受的,你们像用 pip 一样用 npm,就没问题了。。
v2 里面敢黑 python?宝宝你是不想活了.
???赶紧叫 js,php 来主动接锅.
Npm 难用不在 npm 本身,在于 npm 不是 python 的生态.所以都不许好用!
之前不是有个帖子在说:python 性能差是公认的吗?不要用 python 做复杂业务就可以了吧,我猜。。。
另外,conda 新建 environment 也很简单啊,多版本管理没什么问题的


