V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  vwxyzjn  ›  全部回复第 1 页 / 共 1 页
回复总数  8
2018-01-04 18:31:57 +08:00
回复了 serge001 创建的主题 Python Python 的包管理感觉怎么这么不优雅。。。
@ipwx 因为我最经常用 python 啊,但是想到以后写的代码会有这样重现问题就很头疼…
2018-01-04 17:18:07 +08:00
回复了 serge001 创建的主题 Python Python 的包管理感觉怎么这么不优雅。。。
@scriptB0y,@ipwx 您们说的约定俗成,向下兼容都是好的实践,但我说的重现能力…… 另外 js 未必就不能做你们说的最好实践。

所谓重现能力是我今天写的代码明天还能跑,而不是因为一些莫名其妙的原因不能跑了。和您们讲个自己的例子吧,我第一次写的小 /中型项目 https://github.com/streettraffic/streettraffic 用到了 websockets==3.3 这个依赖。我 setup.py 是乱写的,连版本号都没写,所以我写完几个月重装时发现跑不了了,后来 debug 之后发现是 websockets 高等版本破坏了原有的 api。

哪怕我在 install_requires 里面写了 websockets==3.3,只要别人在安装我的项目之后再安装一个项目有用到 websockets 的更高版本,我的代码就会报错了。

是的,我可以维护这个项目去修 bug,但是每个人的精力是有限的,并且你主要工作的项目也会变,所以我并不愿意改这个 api。我并不认为这样是错误的,并且我认为我写的代码如果能跑,便不应该因为这种依赖问题到后期某一天报错。
2018-01-04 17:02:18 +08:00
回复了 serge001 创建的主题 Python Python 的包管理感觉怎么这么不优雅。。。
@jhdxr 感同身受… 经常是 pip install 后出现一些奇怪的红字,然而无休无止无意义的依赖 debug 开始了
2018-01-04 16:53:57 +08:00
回复了 serge001 创建的主题 Python Python 的包管理感觉怎么这么不优雅。。。
@scriptB0y 另外我感觉我们说的似乎不是一个东西。我感觉您说的那个 requirement_base.txt 似乎更像是对项目的高阶描述:说的是我们主要的依赖是这些包,而我说的是 python/pip 缺乏重现能力。

> 基本不会冲突(我没遇到过),因为大家一般都是规定最低版本。如果真有两个包最高版本冲突,那说明其中有一个包太久不更新或者本身就存在问题,具体解决吧。

您的意思是似乎是说,出现了依赖冲突我们再想办法解决,而我是说,如果 pip 和 npm 一样,我们连这样的冲突都不会碰到,所以在这个角度上,pip 的设计是有缺陷和落后的。

另外您很少遇到不代表别人很少遇到,我 debug 这种依赖相关的 bug 应该不算少,总是要 pip uninstall,install,然后通过一番努力终于代码能跑。然而我厌倦了这种 debug,既然有 npm 这种一键解决你依赖问题的安装方式,为什么每次要自己找麻烦去手动解决依赖 bug 呢?
2018-01-04 16:37:59 +08:00
回复了 serge001 创建的主题 Python Python 的包管理感觉怎么这么不优雅。。。
@xpresslink virtualenv 和 pipenv 都没有解决 dependencies collision。请看我刚刚写的例子。
2018-01-04 16:35:32 +08:00
回复了 serge001 创建的主题 Python Python 的包管理感觉怎么这么不优雅。。。
@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,也许这样会给你一些缓冲的版本来解决这种依赖冲突。

但是简单来说,你的程序没有重现的绝对保障。换句话来说,你的程序能不能跑有些看运气。
2018-01-04 12:22:53 +08:00
回复了 serge001 创建的主题 Python Python 的包管理感觉怎么这么不优雅。。。
@scriptB0y

这样不好… 我都不知道小型的项目要怎么手写这个
requirements.txt 。难道挑几个自己 import 的包写吗…?那万一漏一个怎么办,万一你选的这几个包依赖的包版本有冲突怎么办?
2018-01-04 11:15:47 +08:00
回复了 serge001 创建的主题 Python Python 的包管理感觉怎么这么不优雅。。。
@scriptB0y 不同意您的回答

> 我假设你说的是管理依赖?一般写到 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 跑。也许某天某些包升级了,我的代码就失效了,这实在是让人担忧和痛心的事。

希望大家理性看待。
关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2890 人在线   最高记录 6679   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 10ms · UTC 13:32 · PVG 21:32 · LAX 05:32 · JFK 08:32
Developed with CodeLauncher
♥ Do have faith in what you're doing.