夏天不是读书天

#清空草稿箱计划# 原文创建于 2023 年 6 月 24 日。

回上海的这一天上午,我需要去附近的乡里走一趟。

桃市附近多了一家养蜂场,叫小武养蜂场。风景区附近的围墙上有一些新的标语。下一句是“仰望星空展未来”,上一句你肯定猜不出来——“一心一意跟党走”。电信营业厅戴着口罩咳嗽的店员,提醒我新冠还没有过去。天气很晒,但风很凉爽,耳机里是 Vampire Weekend 的那张《Father of the Bride》,一张专辑刚好够打一个来回。在这样的街上,太阳浇灭了所有购物的冲动。更何况这里没有城市里的那些陷阱——没有音乐,没有香氛,没有创意十足的广告,没有精致完美的女人在墙上直勾勾地想把你看穿。只有奄奄一息的老年人和中年人在发烫的遮阳棚下玩手机和打盹。我还是想买一些东西,只想买一些必需品。去两元超市给小巴买了一个橡胶球,两块钱。不过每次送给它的球都玩不了几天——要么被它咬烂,要么被邻居家的狗偷走。然后去隔壁的超市买了一瓶矿泉水,也是两块钱。

从上海回家是在父亲节前一天,我在火车上看完了安妮·埃尔诺的《一个男人的位置》。听了《昨日之海》的某期播客后买了这本书和《一个女人的故事》。某一天我把《位置》读了个开头,然后放在我的床边。一放就是许多天过去。这种情况多了,床头柜变成书柜,堆栈变成积木。果然旅途才是最适合阅读的环境,单程就可以读一本书。

这本书的阅读体验像是某个人的博客,一个为爸爸写的博客。很多人小学的时候都会写一篇《我的爸爸》这样的作文。成年之后,直至爸爸去世,却很少有人再写一篇《我的爸爸》。我突然想到,世界上某个人也许会在爸爸的葬礼上读他写的第一篇《我的爸爸》:我的爸爸是一名公交车司机。他有一双结实的大手,可以很轻松地把我抛起来,然后又稳稳地接住。他不抽烟,也不喝酒。他戴墨镜的样子很酷。他告诉我酷有很多种,外表酷只是其中一种,做事情认真也是一种酷,帮忙别人也是一种……

读的过程中,我不断想起从小到大我熟悉的那些“大人”。想起每一次的婚礼和葬礼,那些家族里的男人们。想起他们在这个世界上的位置,以及他们为了把下一代推离到更远的位置的努力。他们从没有想过有另一条路可走,总是像个硬汉。他们快乐吗?他们的孩子快乐吗?也许从没有人问过他们。祝他们夏天快乐。

干杯

最近花了很多时间在准备一个年会节目。整个过程记录到了下面的短片:

https://www.bilibili.com/video/BV1Re411E7uX

整体的设计是这样的:节目一开始会放这个短片,当画面放到走向年会会场的时候,我们就真的入场。入场后画面会是滚动的歌词(上面的视频里已经被替换为实际的演出画面)。滚动的时长就是演唱的时长(三分钟),唱完刚好会出现演职员表。

整体基本按照计划执行,唯一的遗憾是前面的部分因为网速原因有些卡顿,卡点全都没对上。除此之外还有很多乌龙:话筒放错了位置,导致我要仰头唱,Qingfeng 要低头唱。上场前被谁碰了一下变调夹,导致六弦有点松。演出上午我还在弹错和唱错,反而正式演出却没出问题。再往前一天,还在纠结吉他收音和话筒支架问题。再往前半个月,因为高音唱不上去、吉他和弦切换不熟练焦虑,嗓子疼了好几天。虽然问题很多,最后呈现的效果还不错。

短片里很多穿帮镜头也没有时间打磨,比如上场前和演出时的衣服不是同一件。因为大家都在上班,经常随便抓一个没开会的同事帮我拍视频,大都只拍了一两条就用了。本来还计划了一些长镜头和分镜画面。因为时间有限,没法一一实现。

很开心的一段经历!剪短片、排练、演出都很快乐。关掉会场的灯,大家一起看我做的视频的感觉,让我想起来大学那次做的幻灯片。也许我应该去逐梦演艺圈 :P

最后贴上同事 Steve Wang 年会后写的诗(词)作结:

御街行

岁末寒风冬日暮,春将至,来时路。
久别年会今时归,料定狂欢无度。
铃鼓轻拍,沙锤细响,吉他低吟谱。
深度影视当乱舞,几月天?六点五。
彩排剪辑需几步,八仙各显其术。
用心数只,人生几处,今宵惟一赋。

 

Flask 已死,FastAPI 永生

好险,刚刚要写一个新项目,执行了 pip install flask。等得无聊所以打开了知乎,突然看到首页推荐的这篇《Flask 已死,FastAPI 是未来》。看到一半吓得我赶紧按下 Ctrl-C,然后重新执行了 pip install fastapi。好快!不愧是 FastAPI,连安装都这么快。

Flask!Flask!你怎么了?Flask~Flask~你不能死呀!我跟你相依为命、同甘共苦了这么多年,何况我的书还没有写完,想不到今天白发人送黑发人……

blank

咳咳,说回正题,2021 年我写过一篇《请不要把 Flask 和 FastAPI 放到一起比较》。不是同一个等级的框架拿到一起比较没有意义。这篇《Flask 已死,FastAPI 是未来》从一开始的标题就是错的。

除了比较上的问题,上一篇文章里最后提的问题现在有答案了吗?

各种对比文章贴出来的 hello world benchmark 对于开发生产应用来说有多大的意义?这里的 benchmark 背后有没有任何的 hacky?异步是否等同于高性能还是要看情况?框架本身的性能在一个请求处理流程中占多大的影响?asyncio 的生态怎么样?

同时我也指出了一些 FastAPI 的问题——现在 FastAPI 营销至上的项目运作方式改变了吗?

从长远看这些大都是一些临时问题,而且 FastAPI 作者已经开始全职开发开源项目,这些问题在未来应该都会慢慢得到改善。指出这些是希望更多的人可以客观看待 FastAPI,吹捧并不能让一个东西变得更好,参与开发、介绍用法和回答社区提问是比盲目吹捧更有意义的事情。我当然期待 FastAPI 能够越来越好,也期待看到有更多优秀的 Python 框架出现,但我不喜欢过度炒作、盲目的吹捧和错误的对比。

如果一个人即没有深入了解 Flask,也对 FastAPI 的整体状况一知半解,然后突然跳出来写了一篇《Flask 已死,FastAPI 是未来》,他的目的是什么?炒作啊,朋友。标题党也就罢了,到处都是逻辑漏洞和事实错误这也行?

精彩片段赏析

前两天在 Twitter 上对这篇文章发了一点想法。大概是我的语言能力退化,导致很多人没看懂我的反讽和调侃……所以还是好好说话,摘评几条原文的内容:

其实我这篇文章,也可以叫做「Django和Flask之死」,但是在框架应用场景角度来说Flask和FastAPI对比更合适,而Django直接和FastAPI相比有一些差别。在一些商业场景(例如CMS)Django依然是首选,而Flask(甚至FastAPI)看起来更像个「玩具」,所以Django短时间不会被取代(Flask这些年不是也是没取代的了嘛)。
Django REST Framework(DRF)
Django主旨是为了在后端生成 HTML,而不是创建现代前端(如 React、Vue.js )或与其通信的其他系统使用的 API。所以FastAPI其实和Django REST Framework直接对标,它们主要场景都是构建 Web API,但是名字上也可以看出来,DRF还是依托于Django框架,所以缺点一样。

既然作者能看出来 Django 和 FastAPI 有差别,也了解「FastAPI其实和Django REST Framework直接对标」,那么就看不出来 Flask 和 FastAPI 在框架应用场景角度有差别?所以为什么不用 APIFlask 这种和 FastAPI 对标的框架,而是挑了 Flask?

Flask本来的优点是灵活性和极简主义,但这意味着很多很多组件需要自己造,这个要不然需要公司够大专门有开发者开发和维护,要不然得个人能力极强,否则插件很难达到生产级别,这就造成Flask的第三方插件质量层次不齐,且无法保证长期维护。就像我上面说的那些库,现在来看,其中已经很多不再维护了。

这点蛮中肯,Flask 扩展的质量和维护状态确实参差不齐,这也是为什么我要发起濒危 Flask 扩展拯救计划并创建这个 Flask 扩展状态监控项目。那请问 FastAPI 呢?首先 FastAPI 是否有这么多「FastAPI 扩展」可用?其次 FastAPI 的第三方插件就不会出现这些问题?说到底这是所有开源项目和社区生态都会遇到的问题。

所以即便是今天,你想用Flask构建一个API服务,还是要东拼西凑各个组件,其中某些组件有些没及时更新的地方要自己动手解决,这对于老手来说还好,对于新人来说很痛苦,尤其是你想要应用现在最新的实践方案和理念,只能望而兴叹。

首先作者了解 Flask 和 FastAPI 相比,后者的主要场景是「主要场景都是构建 Web API」,接着又说 Flask 生态构建 API 需要东拼西凑。听起来不太对劲?

另外 Flask 生态中类似 FastAPI 这种提供 API 整体解决方案的框架都被作者忽略了?随便列几个:

东拼西凑就一定是缺点?不熟悉这些工具的人选择打包方案,熟悉的人选择自己组装,这有什么问题吗?

这个时候Flask并不想接受改变,社区迟迟的不加入aio的支持,另外Flask原作者也去写rust了,把项目交给了2个维护者(现在只剩一个人了)。

到这里文章就开始有些不对劲了,喜剧/戏剧效果逐渐增加……Flask 开始被拟人化了。Flask 是谁?是谁要求改变?Flask 说了啥表示不想改变?

Flask 作者把项目交给了 2 个维护者?现在只剩一个人了?!Flask 真的好惨……可是这些事情都是什么时候发生的?虽然我最近两年开始工作已经没怎么给 Flask 提交代码,不知道哪天被踢出群聊。但是至少我从 18 年到现在一直是 Flask 的维护者,这些事情我怎么一点都不知道?

在Flask的那个时代,代码执行是单线程、同步的,这意味着要依次处理请求,前一个请求完成前,其他请求消耗在等待 I/O 操作上。而asyncio是最好的解决方案,它让I/O成为异步操作,无需等待任务完成即可获取任务结果并继续处理其他任务请求。

好奇 Flask 的那个时代是哪个时代呀?听起来像是妈妈在讲小时候的故事呢。Flask 2.0 已经添加了有限的 async 支持Quart (Flask 的 ASGI 实现)已经合并到 pallets 组织,作者正在推动 ASGI 支持的 Flask。这些都是这个时代的 Flask 在发生的事情哦。

而FastAPI天生支持并发和异步代码,代码写对了就可以在效率上达到极致,所以它被认为是目前最快的Python框架,效率和NodeJS或Go接近。当速度和性能至关重要时,FastAPI 是最佳选择。

嗯,这个我无从反驳。你说快就是快,宇宙最快 Web 框架。

另外由于集成了Pydantic,所以非常容易在项目中添加ORM(如SQLAlchemy),从请求中获得的对象可以直接传递到数据库,因为已经做过数据验证。反之亦然,可以将从数据库获取的对象直接返回。
相对的,Flask这方面的缺失的。

完蛋,Pydantic 对 Flask 发起了单方面安装制裁。当你在 Flask 项目里试图引入 Pydantic 的时候,就会出现安装错误“Warnning: Pydantic is strictly forbidden to installed into a Flask project. Your behavior has been reported to PAFAFC (Pydantic and FastAPI and friends Committee).”

再补充一点。FastAPI无论看项目名字还是介绍都能感觉出来它是用于构建API服务的,事实上FastAPI自己的核心代码也确实是这样的,可以说它不是一个传统的、完全自己实现的框架,它更像是一个集各家之长的框架,从一个空壳开始,把需要的、适合的组件组装起来。例如它没有模版引擎,如果你确实需要用它实现一个web应用要渲染模版,你可以再组合你想要的选择,当然还可以用Starlette内置的Jinja2(是的,也是Flask内置的)

作者对于 Flask 和 FastAPI 两者定位不同的认识真是越来越清晰了呢。不过「组合我想要的选择」不就变成前面说的 Flask 那样东拼西凑了嘛,不好。还有就是 FastAPI 为啥要在介绍模板引擎的文档里让我安装 Jinja2 呢?看来「相对的,FastAPI这方面是缺失的」。

上面提的是FastAPI的优势,但是也不能说明Flask已死,我为什么会这么觉得呢? 主要还是看开发者和用户的人气。

重头戏来了,下面终于到了对于「Flask 之死」的凄惨景观的详细描写(注:这几点后来作者看到了我在 Twitter 上发的东西又自己做了补充和修改。这里我引用的是原文)。

1. 社区活跃度。例如项目的Issue和Pull Request数量,Flask都是个位数,和FastAPI相比根本不是一个水平。这其实侧面证明项目不再活跃,因为如果活跃的话,老的用户会有更多需求,它们不来说明已经离开,而新的用户意味着有各种问题,文档即便足够全,其实我们要知道还是会有很多用户来提问和贡献代码的,没有就说明用得少。

如果你经常参与开源项目或是自己开发了开源项目,通常会了解到,一个流行的项目想要把所有的 issue 和 pull request 都处理掉是很难的事情。而 Flask 能做到这一点反而是维护团队的努力尽责和项目本身足够成熟的体现:

blank

以及对 issue 和 pull request 快速响应的体现:

blank

如果你想知道有多少人在用 Flask 和 FastAPI,有两个参考数据,一个是 GitHub 上开源项目的用户数量统计。这些可以在两个项目的 GitHub 主页直接看到。

FastAPI

blank

Flask

blank

另一个数据是 PyPI 下载量,这个可以在 PyPI Download Stats 上看到。

FastAPI

blank

Flask

blank

另一方面,不同的项目对 issue 的使用策略是不同的。有的使用自己的 issue tracker,有些鼓励用户来提问。Issue 和 pull requests 不仅不能用来表示项目活跃度,过多的数量反而能说明一个项目的维护状况堪忧。堆积的 PR 对于用户和开发者来说都是灾难。以 FastAPI 为例,你看看现在的 PR 列表里都是什么?项目不如改名叫「FastAPI 文档大全」好了。你觉得这样会让提交代码贡献,修复 bug 的人有很好的体验?

blank

FastAPI 有不少 issue 在建议作者创建开发团队,摆脱当前这种低效的维护模式。类似的抱怨有很多,我不想去翻历史,这里仅以置顶 issue 里的一则回复举例:

blank

评论中提到的是这个 PR。一个 bug 在 2022 年就有人试图修复,但是到现在都没有被处理。而且报告相关 bug 的 issue 已经被转换成讨论。最后一条是用户在建议把这个讨论转换回 issue:

blank

没错,FastAPI 本来有几百个 issue(好活跃,对吧),某个时间点被批量转换为讨论,谁知道里面有多少是没有被处理的 bug report。谁知道这 646 个 PR 里有多少是需要被优先处理的 PR。我在 2020 年也提议把文档翻译放到单独的仓库,后来这个 issue 也被转成讨论了。到现在贡献者依然被这个问题困扰

blank

2. 讨论度。也就是博客文章,Stackoverflow等网站咨询和讨论的热度,其实可以感受到,已经没什么人写Flask相关的内容了。

作者写文章是可以随口就来的?博客文章不好统计,那么以 Stack Overflow 来看。抛开问题总数量,因为两个项目创建时间不同。但就提问频率,以上次发推文和现在两次截图的数据来看,和 Flask 相关的问题都创建的更频繁。

FastAPI

blank

Flask

blank

3. 开发迭代的频率。翻一下commits,可以看到Flask只有一个维护者会偶尔修修bug,没有什么大的功能特性开发。

开发迭代的频率和活跃度也是作者强行建立的联系,不过结合 FastAPI 的运作方式,两位作者倒也是「双向奔赴」了。「偶尔修修bug,没有什么大的功能特性开发」有什么问题吗?这就是维护者应该做的事情,大的功能特性又不是每天都有。而且作者是不是没有看 FastAPI 的 commits 历史?你肯定猜不到三千多个 commits 里有一千多是 bot 在更新 changelog。再猜猜 FastAPI 最新一个 release 都有哪些新功能?11 个改动里有 5 个是在更新 README 上的赞助商列表哦:

blank

4. 灵魂人物的影响力。Flask的灵魂人物,也就是项目的发起人其实早就不再参与项目了,搜一下项目贡献记录可以看到Armin Ronacher上次参与开发已经是6年前了。

这条实在不知道说什么好。我创建了项目我就得绑死在项目上直到生命最后一刻是吗?引用一下我在 Twitter 上的回复:

开源项目一定不要创建 GitHub org,项目再流行也要放在自己的账号下。不要成立什么开发团队,PR 要自己慢慢 review,用户抱怨多了,你自然知道哪个 PR 比较重要。还有就是用自己的账号或头像来设置 bot,这样即使你哪天兴趣转移了,用户会以为你一直在参与。斯人已去,灵魂犹在。

我真的佩服 FastAPI 作者这一招用自己的账号来作为 bot,用户以为你在活跃,而这个 PR 哪天能够被 merge 还要多烧几炷香:

blank

一边说自己忙得不行,一边又坚持把项目放在自己个人账号下,坚持自己 review PR。这就是灵魂人物?

后记

终于写完了。没想到只是偶然在一台没有屏蔽推荐首页的电脑上打开了知乎,最后要浪费这么多时间和精力。我想肯定会有人看了开头就急着评论,说「FastAPI 如何好用」或是「Flask 如何不好用」甚至是「Python 不如 XXX」。这些都是离题的讨论,我不完全否认这些观点,也并没有谈及这些。这篇文章只有两个目的:

  • 强调不应该把两者放到一起比较
  • 指出那篇「引战文」中的错误观点和事实偏差,顺便指出一些 FastAPI 的问题

对于程序员来说,你可以使用任何框架,你也可以使用任何编程语言。程序员不就是要随时接受改变,随时学习新的东西吗?没人要你一辈子只能用 Flask 或是 Python。另一方面,即使别人都用 FastAPI 了,我用 Flask 又会怎么样?工具而已,只是按照需要做出适当或喜欢的选择。但是你起码要看一看文章再发表评论,而且也不用看到什么观点就相信什么观点(尤其是没有论据、结论先行的文章)。

同时建议 FastAPI 推介者保留一点体面。新事物的建立不一定要踩在已有事物的坟墓上。挑起对立只会导致 Python 社区的混乱。最后再引述我在上一篇文章的想法作结:

从长远看这些大都是一些临时问题,而且 FastAPI 作者已经开始全职开发开源项目,这些问题在未来应该都会慢慢得到改善。指出这些是希望更多的人可以客观看待 FastAPI,吹捧并不能让一个东西变得更好,参与开发、介绍用法和回答社区提问是比盲目吹捧更有意义的事情。我当然期待 FastAPI 能够越来越好,也期待看到有更多优秀的 Python 框架出现,但我不喜欢过度炒作、盲目的吹捧和错误的对比。


相关链接

PyCon China 2023:濒危 Flask 扩展拯救计划

月初参加了 PyCon China 2023, 做了一个关于 Flask 扩展生态的演讲。不太算是技术分享,讲故事为主。主要的契机是最近尝试把几个失去维护的 Flask 扩展通过各种方式「救」了回来,所以借此机会分享一下经验,也号召大家多多参与开源项目。

演讲介绍

看着一个又一个 Flask 扩展失去维护,不再兼容新版本的 Python 和 Flask,我们能做些什么?在这个演讲里,我会介绍最近我和一些被遗弃的 Flask 扩展打交道的经历,包括如何更新一个古老的 Python 开源项目,以及正在实施中的一个拯救计划。如果你来自其他开源社区,那么这里介绍的经验或许也会帮到你。

录像和幻灯片

P.S. bilibili 认定金正恩的照片是违禁图片,留半秒都不行,最后只好贴了一只马在上面。浪费二十分钟。

照片

blank blank

蚊子偷看我写书

家里太舒服,所以决定去图书馆写书。起得太晚,到达已经是十一点半。写了半小时,午饭时间到。想找到特定颜色的共享单车,结果一直找到吃饭的地方。

午饭后脑袋昏沉,睡了一觉,压得手臂发麻。醒过来两眼失神,无法聚焦。感觉越来越热。不知道为什么 VPN 节点全部失联,换了备用服务器,然而命令行还是无法连接 GitHub。打开几个网页,但是早已没有兴致解决这类问题。政府可真是神通广大,随随便便就浪费掉我三十分钟。感觉越来越热,决定打包离开。

图书馆有两个天井,四个位置都有人。徘徊了两圈,终于等到一个空位。今天风很凉爽,一年里少有的好天气。树叶在旁边沙沙地响。下午四点零八分,开始写书。四点十分,发现一只蚊子在附近转来转去,好像要偷看我的书稿——我那写了两年还是一团浆糊的书稿。经过一阵周旋,四点十一分,蚊子终于被我杀死了。

如果没有工作的话,我可以一天一天地在城市里游荡。从一个座位到另一个座位,从一栋建筑到另一栋建筑。直到把想做的事情做完,直到我对这个地方感到厌倦。如果没有鬼魂,这个世界就太没意思了。如果没有自由的人,那这个城市还有什么希望?

P.S. 距离我信誓旦旦宣称的交稿时间已经过去 5 天,距离跟编辑承诺的交稿时间还剩 25 天,距离合同上的交稿日期还剩两个月满一周年。

代码厨房欢迎你

代码厨房是一个面向编程和开源爱好者的社区。社区的主体是坐落在 codekitchen.community 的论坛。这个论坛的前身是创建于 2019 年 1 月 11 日的 HelloFlask 论坛(HelloFlask discuss!),因为论坛服务器一直在海外颠沛流离,所以访问起来并不是很顺利。最近把论坛以及 628 位 HelloFlask 原住民一起搬家到了香港,改头换面变成代码厨房社区。

「代码厨房」最早是我创建的公众号的名字。同一时间注册了 daimachufang.com,想要在这个网站上放些什么已经不得而知。后来公众号一再改名,代码厨房已经不见。再一次想起来是在去年 10 月, 29 日心血来潮去参加中国开源年会的开源集市。作为现场唯一一个个人展位,我带去了两个项目。一个是方学园,另一个便是代码厨房俱乐部

blank

出发前一天为代码厨房俱乐部更新了 daimachufang.com,也就是下面的样子:

blank

俱乐部现场成立,现场报名。报名单上收集了十个人,最后筛选到五个。算上我自己,六个人在一年内完成了四次聚会。大家互相带来很多新想法和思考,也玩得很开心,但逐渐有点忘记最初想要做什么。于是,在 2023 年的 10 月 22 号,最后一次聚会,大家回到了报名的地方——微软 Reactor。我在那里重新介绍了代码厨房社区的构想

代码厨房的核心构想是「一个让人快乐和放松的编程社区」,主要的板块是:

blank

不论你是当下、曾经还是未来的编程爱好者,都可以加入我们。代码厨房欢迎你!

APIFlask 2.0 版本发布

一边上班一边赶工做开源项目真是太累了。更不用说还要一边焦虑写书的进度。不过这次 2.0 版本基本把想做的功能都完成了,剩下两个大的功能(为蓝本拆分单独的 OpenAPI Spec、解耦 marshmallow)实在是没精力加进来了,只好放到 2.1。

APIFlask 2.0 版本的 codename 是 Gongqing(年初我从五角场搬到了共青森林公园旁边。没错,1.0 版本是 Wujiaochang)。

回到正题,这次最主要的一个变动(breaking change)是把所有 input 装饰器的参数改成了关键字参数。

@app.post('/pets')
@app.input(PetQuery, location='query')
@app.input(PetIn)  # equals to app.input(PetIn, location='json')
def create_pet(query_data, json_data):
    pass

关键字参数的名字默认是 {location}_data,通过 arg_name 参数可以自定义。这个改动让我删掉了很多 hack Flask 的代码。推动这个功能在上游 webargs 实现,所以不用加代码在自己这里。再加上一些改动已经在 Flask 实现了,又删掉一些。非常轻松。理想情况是,文档越来越多,代码越来越少。

如果你感兴趣的话,下面是 2.0 版本的详细内容:

 

共青森林公园吉祥狗

下雨天和女朋友去共青森林公园散步。因为只有一把伞,所以不得不在中途避了一刻钟雨。我们聊到古代人在这种廊桥避雨,可能一避就是一整天。她说书生一般会在这里邂逅狐妖,然后相谈甚欢。我说然后雨停了就各自走了,再也没有见过。没有烂俗的故事,不给后人拍电影的机会。

雨天的共青森林公园人很少,让人放松。雨稍停的时候,遇到两只非常有戏剧效果的狗。想说服它们放下安逸的生活去逐梦演艺圈或是戏剧圈,它们不为所动。尽管从一路中分到底的毛发可以看出来它们被淋得很惨,但它们说喜欢这样,喜欢这么简单的生活——每天在公园里探险,淋雨,晒太阳,吃游客供奉的食物,汪汪,汪汪……我把放在包里随着我颠沛流离已经变得稀碎的饼干送给了它们。

建议园方让它们俩做「共青森林公园吉祥狗」(当然前提是它们愿意),取代那两只淋多久也不会中分的松鼠。

P.S. 推荐雨天的共青森林公园。记得要穿拖鞋。


blank
blankblankblank

自行车叨位去

最近开始骑车上班了。 单程 20 分钟左右,每周去公司三天的话,一周就可以获得 120 分钟运动时间。在此之前,我会坐九点二十五分出发的那班公交,只需要 15 分钟。不过我经常在九点二十一分才出门。这样下去,迟早有一天会有公交车弃我而去、而我喘着粗气远远目送的画面出现。

在中原城市广场附近,有一个很大的路口,和一个时间超长的红绿灯。我经常在那里等红灯变绿的时候发呆。在路上我会听根据播放历史生成的随机歌单,上一首也许是周杰伦,下一首可能是巴赫。有一次我经过那个路口,耳机里刚好播放到拉赫玛尼诺夫第二钢琴协奏曲的第一小节,突然就很想哭。那个时刻时间变得很缓慢,那个路口也变得更大了,像是一面湖。我漂在上面,风推着我走,周围的人都是我最熟悉的朋友。我们一起在湖面上荡着,吹着凉爽的风,晒着九点多的太阳,又或者是黄昏时柔和的太阳。这一天就到这里多好。

骑车上班的时候,生活又开始流动起来。虽然绕来绕去无论怎么组合,也都只有那么几条路。但是因为背景音乐不同,每天都像是新的电影。到了公司我并不直接进去,而是沿着路继续往前骑,再绕江湾体育场一圈,这一圈让我心情平静。如果不够平静,那就再多一圈。

春天快乐

除了一堆药,医生还开了一个颈托,三百五十块。付款前犹豫了两秒。果然,淘宝只要两百块。回家前路过体育学院旁边的二层破败小楼,看到有小吃摊就拐了进去。躲开一地的猫,发现只有炸香肠和炒饭炒面。虽然炒饭和炒面有一堆排列组合,但我还是走掉了。没有车篮不说,买了去哪里吃呢,回到家估计要冷了。过去之前心里想着的是鸡蛋灌饼和火烧,至少也是手抓饼。

经过大润发,看到高大的樱花树,也可能是山茶树(总之是会开红色花朵的某种树)。想起来再往前是民星公园。没有犹豫,径直转了过去。小小的公园,还算精致。树很多,很密。有些开了花,有些发了新的叶子。这个时节,如果不开花,也不繁茂,春天会责怪你的。七拐八拐转了一圈,除了两三个带着孩子的中年男女,其他都是老年人。穿着精致的、化着浓妆的、悠闲的、昂扬的老年人。尽管在不可避免地走向衰败,但这个公园和春天都是他们的。可是过了几十个春天,不会感到腻烦吗?围着这小小的公园,一圈又一圈,不会感到疲倦吗?也许我不该逆时针走,这样他们就不用被我观察,我也不用生出那么多混乱的念头。

公园中央是一团浑浊的湖,长满了各种水草。没有鸭子。鸭子大概都飞去看海了吧?现在天气这么好,至少也要去共青森林公园里度个假。湖边一圈围栏上挂着三个人——白手套先生在压腿,白口罩小姐在拉伸胳膊,另一个呢,是我,穿着白色的球鞋在写日记。

说到底只是不想回家。期待有另一件计划之外的事情发生。期待迎面突然走来一个人,拉着我的胳膊说,快跟我走,没有时间解释了……什么?合什么 PR!?等到第二个 code owner 看到之后 approve了 CI bot 会自动 merge 的……&%¥%……

好了,该回家了。白手套先生和白口罩小姐,春天快乐!

七手八脚的写诗

一个人是怎么样开始写诗的?在工厂里打着工,突然就开始写诗了,突然就自杀了。我想诗是情绪和感觉的完美出口。一个灵魂不受拘束的世界。一种很容易就实现完美、精巧和纯粹的东西。在这个世界里活得辛苦,就去另一个世界。

更重要的是,写诗好快乐。像是落在奇思妙想蹦床上。像是突然多长了几只手几只脚,可以「七手八脚」的走路和说话。对于地球,我顶多可以写一句「今年地球转得也太快了」,而其他人却可以写出:

  • 地球吓了一跳 / 死了十几万个细胞
  • 绕了一圈 / 我悲哀地发现 / 我终究还是 / 逃不出这地球
  • 何以这晚之后 / 我竟想去习武保护地球

如果不管好坏的话,写诗的快乐可以和涂鸦、画漫画、制作梗图、和陌生人聊得投机后相忘江湖并列。

2022 年总结

今年地球转得也太快了。听同事说,开始工作以后,地球转速加快是正常现象,结了婚和有孩子后还会有额外加成。考虑到地球转速问题,我想这份总结不宜再拖下去。

一月开始了第一份工作。找工作时还希望可以去办公室呆一呆,后来就变得越来越懒,一周只去一两天。三月初侥幸离开上海,更是在家呆了半年才回来。工作上倒也得心应手,只是工作之外有太多的事情想做——但没有足够的时间和精力。这渐渐变成我最大的困扰。

我不是精力旺盛的人。无论去不去公司,工作之外挤出的时间常常都是疲惫不堪的浑水。在这少得可怜又困倦的时间里,经常纠结该做些什么。要看这本书吗?还是那个电影?写书?做开源项目?最后多半躺在床上听歌玩手机,至多做些明天的规划。

听到一首歌唱:

如果继续这样 / 我还是我吗 / 我还喜欢我吗
或者我应该死去吧 / 总好过变得更差

又听到另一首歌唱:

I don’t want to live like this
But I don’t want to die

音乐也许是解药(不,早起才是)。从张玮玮的演出回来后,有了继续学吉他的念头。十年过去了,是时候开始文艺复兴了吧!买来吉他练习一阵后,想起高中随吉他一起卖掉的那本李志野孩子吉他谱。因为李志被封杀,导致那本吉他谱已经买不到。厚着脸皮翻出十年前的豆邮,问买家能不能把那本吉他谱卖回给我。目前还没有收到回信。

去年开始不再完整记录时间花销,但也有 1815 小时,今年只有 512 个小时(6%)。

blank

在开源项目上投入的时间比写书多了一倍。除了发布 APIFlask 1.0 和 Bootstrap-Flask 2.0,也给 Flask 实现了几个小功能:

  • 给 flask run 命令添加 –debug 选项(#4779
  • 允许视图函数返回列表作为 JSON 响应(#4672

虽然书没写完,倒是更新了《Flask 入门教程》第三版

做了两个演讲,一个是在 COSCon 2022 做的闪电演讲(实际是开源集市的路演,不过摆摊比演讲有意思,还能认识新朋友);另一个是在 Python Meetup 做的关于 Python 和 OpenAPI 的分享(实际是炒冷饭,不过有额外加料)。没记录时间的还有一个在公司做的关于 Python 编程规范的分享,以此还在年底拿到了「2022 年度新秀奖」。

明年会更少记录时间,比如娱乐活动分类就已经存档——开心很重要,不再追究时间了。

这一年因为开始上班而过得平淡乏味,没有太多东西可以总结。仔细回想也有一些有意思的事情,比如工作上发生的各种事情,比如代码厨房俱乐部。打算在另外的文章来写,这里就不展开了。

今年的疫情对我没有什么大的影响。上海为了科学防疫而封城时我躲在老家,农村因为科学放开而瘟疫蔓延时我躲在上海。唯一的影响只有愤怒。因为各种所谓防疫导致的伤害、不公和死亡,还有各种愚蠢言论而愤怒。当然,最后除了骂傻屄,已经没有什么想说。

明年只设一个目标:

希望明年可以多过一些离线生活。希望写完书可以好好放松,好好浪费时间。

P.S. 本文中的「今年」指 2022 年,「明年」指 2023 年。