you-get 是一个视频下载工具。我于五年零一周前(2012年9月7日)在 AUR 打包并维护其 git 版本。当时还是叫 python-you-get-git,后来根据 Arch 官方的推荐,与语言没什么关系的软件不带语言前缀,改名为 you-get-git。

youtube-dl 是另一个差不多同时期出现的视频下载工具,一开始主要针对 YouTube 等跨国网站。

选择 you-get 一部分原因是当时它对国内网站的支持更好,另一方面也是支持国产。但是今天,我决定放弃 you-get 了。

五年来,我一直是支持 you-get 的。也尝试过向其贡献代码。目前已经有29个提交被合并,排名第五位。基本上都是一些很小的修改,比如编码问题、未回收的僵尸进程、标题的反转义、ffmpeg 命令的特殊字符转义、支持 python -m 调用、视频链接的解析更新和扩充、进度条的修正和优化,等等。

其实这些年来,我一直想做更多事:

  • 可选地使用 requests 库,以提高解析速度,改善用户体验
  • 支持使用 aria2c 下载视频链接
  • 支持网易云课堂的更高清晰度的未内嵌字幕的视频(pr#1002)
  • 解析更准确的信息
  • 一些其它网站的解析器(比如 bilibili 的 bangumi.bilibili.com 子域)

但是,其中很多都没能完成。勉强完成的也很奇怪:明明是针对网易云课堂的解析,我还非得关心网易云音乐。一直以来,我对 you-get 的修改都是事倍功半。我也曾尝试过更深入的修改,但是牵一发而动全身,往往要改就得改很大很大一部分代码,然后完全没有办法保证其正确性。就像今天的事情一样。

我花了数小时的时间,牺牲睡眠,把命令行选项解析由 getopt 改成了 argparse(pr#2260)。促使我做此修改的原因是,我想下载 bilibili 一整个播放列表的视频。我记得 you-get 有下载整个播放列表的功能。但是我读了好几遍 help 信息,都没有找到那个选项。我记错了吗?阅读源码之后,我终于找到了那个选项。同时,我也看到了在 C 和 bash 代码里经常看到的,一长串 if/else 来解析命令行选项。翻了好几屏。

当一个相对独立的代码片断翻屏时,bug 数量会骤增。

曾经在公司里遇到过一个 case,非常直接地证明这句论断是有多么正确。那个函数刚好超过一屏数行,而在第二屏的那部分代码,有个「}」和「return」的顺序写反了。我也是拿 Vim 的匹配括号跳转功能才发现的。

当然了,不管怎样的代码,不动它是不会出新问题的。然而我动了它。回报我的是两个局部变量名忘记改了:pr#2346、pr#2355。

这种问题在 nvchecker 重构以支持 aiohttp 时并没有发生。为什么呢?我们有测试。如此明显的问题,只要 cover 了必然会发现。所以我可以放心大胆地重构。

you-get 呢?you-get 也有测试。我在提交 pull requests 之后有个习惯:盯着未完成的测试,直到它变绿。如果红了,赶紧看看是不是自己代码的问题,是就赶紧修掉。一些项目(比如 Tornado)的测试本地跑起来要配置环境、装不少东西,太麻烦了,所以我习惯先提了 pr,然后等 Travis-CI 的结果。可这次,测试过了。但是有两个重要的功能却并不能正常工作。

其实呢,对于这种简单的错误,通常 linter 会告诉我的。我有装 neomake,全面支持各种 linter,用起来十分惬意。但 pylint……就像 jslint 一样,我很讨厌它们。因为它们不仅检查潜在的问题,同时还检查代码风格。而代码风格这事是每个项目单独配置的,而不是开发者自己配置好,然后让自己参与的所有开源项目都遵守。不过今天我也终于知道了另一个 Python linter——pyflakes 很对我的味口:只管问题,不管风格。

总之呢,由于各种原因,重写中出了这么两个直接立刻让用户不能用的 bug。很抱歉。一般来说,出错了就改呗。更深入一些,分析一下为什么会出现这种错误,今后怎么避免同样的错误两次出现(早年向 Tornado 提交代码时,Ben Darnell 一个简单的行为教会了我一件事:修了 bug 就写个对应的测试)。但是 you-get 的协作者 rosynirvana 不按惯例来,反而要求放弃此修改。如果就如此也就算了,后续讨论中我意识到了一个真相——为什么我在 you-get 上的工作如此困难?

The best part of you-get is that it's not so pythonic so those who only know js or as3 can take part in, moving from the universal getopt to a py-domain-specific library cannot be a nice idea.

What library nowaday pythonists love do not really matter here because those one know js and as3 can contribute even more in this project.

因为 you-get 根本就是反 Pythoner 的!作为一个 Python 项目,you-get 想要吸引的是 JavaScript 和 ActionScript 3 开发者!

我很震惊。

  • 作为 Python 开发者,我已被他们刻意排斥在外。
  • 作为 JavaScript 开发者,我还是觉得 C 好难写,还是 pythonic 的代码比较好维护啊。
  • 作为 C 开发者,我倒是对这种长达数屏的作用域见怪不怪了。不过重复的逻辑,咱一般会用宏之类的手段给整成声明式的啊。

所以,我的努力注定不会有多少效果。

然后,我看了一眼 youtube-dl。其实就瞟了一眼,也没看出太多东西来,但是

  • 按 URL 进行正则匹配的,网易云音乐和网易云课堂可以分开处理了!
  • 解析器以 class 表达,有组织有纪律!不用用 Python 的语法写 C 了!

我 disown 了 AUR 和 [archlinuxcn] 里的 you-get-git 包。关闭了未完成的 issue 和 feature pr。等修复 argparse 引入的错误的 pr 被合并(不管是只修正问题还是退回到 getopt),事一了,我就删掉仓库,只保留网易云课堂的高清视频解析代码(花了我一整天的)。已安装的 you-get 暂时保留,但首选 youtube-dl,遇到问题有时间就去修一下。已经投入到 you-get 的时间是沉没成本,不必留恋。