Python 的包管理感觉怎么这么不优雅。。。

2018-01-03 23:00:14 +08:00
 serge001

本人前端一枚,习惯了 node 的 npm 之后感觉配置和使用起来都很简单方便,最近学习了一点 python 后,感觉 python 的包管理怎么这么不优雅。首先,配置文件居然是用 txt 文件来写的,二进制文件我用编辑器是无法打开的,然后用 git 也不能很好的版本管理;其次,pip install 是把包全都装在了全局,打开用户目录,一大堆以点开头的文件夹,抓狂。。。

20142 次点击
所在节点    Python
120 条回复
tonghuashuai
2018-01-04 11:38:12 +08:00
XIVN1987
2018-01-04 11:48:03 +08:00
@tonghuashuai
好黑!!
zachguo
2018-01-04 11:56:59 +08:00
@param 经常会看到 node-gyp,不管是安装或者定义依赖用户都不需要做额外的事情。
zachguo
2018-01-04 12:00:09 +08:00
@arvinwangzj 有些包还是会在全局写文件。。即便用了 venv。
zj299792458
2018-01-04 12:07:30 +08:00
你颠覆了我对二进制文件的理解……
scriptB0y
2018-01-04 12:07:48 +08:00
@vwxyzjn

> 实在不知道您是如何得出这个结论的。依赖是 nested 的。也就是有依赖的依赖的依赖。你不用软件来记录这些 nested dependencies,最后的结果就是 inderterministic build.

你说的软件记录指的是 `pip freeze > requirements.txt` 吗? 这样的确可以将所有包的版本准确导出。但是并不是推荐的做法。加入你只依赖了 requests,自动导出会将 requests 依赖的库(当前 pip 所有的依赖)都导出。你自己看到这个文件,都不知道哪些是项目依赖的,哪些是 requests 依赖的了。

我的观点是,Python 的 requirements.txt 应该是可读的。如果你的项目依赖了除标准库的 requests,那么就在文件里面写 requrests (指定最小版本或者不指定),requests 的依赖交给 requests 去搞定。这样不好吗?
ivechan
2018-01-04 12:12:56 +08:00
pip npm go 都不行( C++有包管理?)
求推荐一个包管理做的好的语言入坑?
scriptB0y
2018-01-04 12:13:30 +08:00
@vwxyzjn

> 其中提到很有意思的一个事情,也就是 python 不允许一个 library 存在两个版本。但假如说你有两个包,包 A 依赖包 C@1.1,包 B 依赖包 C@1.2。你用 pip 装完 A 和 B,你会发现包 C 是版本 1.1 *或者* 1.2 (看你安装的顺序)。

发生这种事情本来就是不科学的,不过我还没遇到过。好像 pipenv 在解决这个问题。

我还是坚持我的观点,如果用 requirements.txt 写依赖的话,应该是人工维护,可读,不写依赖的依赖。比如这个:

https://github.com/getsentry/sentry/blob/master/requirements-base.txt
vwxyzjn
2018-01-04 12:22:53 +08:00
@scriptB0y

这样不好… 我都不知道小型的项目要怎么手写这个
requirements.txt 。难道挑几个自己 import 的包写吗…?那万一漏一个怎么办,万一你选的这几个包依赖的包版本有冲突怎么办?
airborne007
2018-01-04 12:23:24 +08:00
@tonghuashuai 漂亮
Sparetire
2018-01-04 12:28:54 +08:00
感觉 npm 比 pip 来得好用,虽然下载的依赖大一点,多一点,不过部署起来挺方便,说 node_modules 目录嵌套深的,那已经是以前的事了,npm install 换淘宝源也不慢,现在 npm 的安装速度和 yarn 也差不多了
crysislinux
2018-01-04 12:29:06 +08:00
npm 把 pip 吊起来打,实际使用问题多无非是因为 js 包很多,更新快,而且还支持多个版本共存。pip 要是处理这种情况,早完犊子了
xpresslink
2018-01-04 13:15:20 +08:00
@vwxyzjn 不会玩 Virtualenv 么? 直接把整个环境打包移到目标环境就行了. 最笨的办法 pip download 包在本地目录.
tairan2006
2018-01-04 13:29:07 +08:00
pipenv 还好吧,另外 npm 嵌套路径过深的问题应该解决了吧已经…
scriptB0y
2018-01-04 13:29:40 +08:00
@vwxyzjn 用到了什么外部依赖就写什么呀,自己依赖的什么必须要清楚啊,总不能稀里糊涂把当前的环境的依赖都生成进去吧。既然是小型项目,那还要有多少外部依赖?

怎么可能漏?

基本不会冲突(我没遇到过),因为大家一般都是规定最低版本。如果真有两个包最高版本冲突,那说明其中有一个包太久不更新或者本身就存在问题,具体解决吧。
jhdxr
2018-01-04 14:00:43 +08:00
@j717273419 10 年前的 Python 现在还能用你怕是在做梦,Python 是两种语言的梗是怎么来的都忘了?

另外上面居然又这么多人支持 pip 觉得没问题我真的是很好奇都是只写过 Python 没写过其他语言吗?
已经有人指出了一个场景,就是不同依赖依赖了某一个包的不同版本。 @scriptB0y 我同意你的看法版本冲突的时候是存在问题,并且这种问题一般无法自动解决。但这种情况不应该报错终止吗?而不是默默的根据安装顺序去决定

依赖文件放在全局而非项目里这个上面已经有人提供解决方案了。

另外就是各种系统 /环境依赖相关的依赖,比如各种需要自己去编译 C 源码的依赖都是坑。

反正 Python 的项目我见到能够拿到手直接 pip install -r 然后就能成功安装依赖并跑起来的项目真的是太少太少了_(:з」∠)_
957204459
2018-01-04 15:53:34 +08:00
没感觉到难用啊
vwxyzjn
2018-01-04 16:35:32 +08:00
@scriptB0y

> 发生这种事情本来就是不科学的,不过我还没遇到过。好像 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,也许这样会给你一些缓冲的版本来解决这种依赖冲突。

但是简单来说,你的程序没有重现的绝对保障。换句话来说,你的程序能不能跑有些看运气。
vwxyzjn
2018-01-04 16:37:59 +08:00
@xpresslink virtualenv 和 pipenv 都没有解决 dependencies collision。请看我刚刚写的例子。
ipwx
2018-01-04 16:49:17 +08:00
@vwxyzjn 你太依赖“每个依赖包版本必须精确到 minor version ”这个事实了。Python 社区的 major version 兼容性和 depreciate api 是好事,JS 那种根本不敢升级依赖包版本的才是耍流氓。开源软件包修个小 bug 是常见的事情,Python 升级依赖包版本我基本都是无脑做的,npm 你升级依赖包版本哪次不是胆战心惊。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://tanronggui.xyz/t/419850

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX