来 COSCon 2022 开源集市一起开发元宇宙

今年的 COSCon 2022 上海线下会场(10/29)有很多开源相关的活动,其中开源集市会有很多开源社区/公司的摊位,每个摊位都可以做任务拿奖品(放心,不是点 star 送周边那种)。看到现场有好几个元宇宙相关的活动,我就想,要不用 Flask 开发一个元宇宙程序吧……所以,在 HelloFlask 摊位,我们会一起开发一个叫做方学园的程序。这是一个虚拟校园,每个人都是一个方块,可以为自己设置不同的颜色和边框圆角。学校里的建筑也都是方块,类似这样:

虽然这个项目还在很早期的阶段(突然心血来潮,然后刚买了域名的那个阶段),但我想这大概就是元宇宙,对吧?

我准备的奖品有几本书和一些 Flask 贴纸。趁 Flask 还没换上新 logo(嘘,内部机密),这次要把剩下的所有贴纸都送掉。

如果你有自己的开源项目,也可以来这里做分享,或是放到 HelloFlask 摊位来吸引别人参与。

感兴趣的话,用下面的链接报名活动吧(免费):

下面是一个 HelloFlask x COSCon 2022 微信群聊,欢迎想来参会的朋友加入:

周六见!

待业五年后的找工作经历

这篇文章记录了我去年年末找工作的经历。最大的感想是,程序员找工作不一定需要刷题,很多公司是不考算法题的(除非目标就是那些字母组合公司);其次是要有一些公开作品,比如开源项目,这样可以避免被使用某些单一维度评价;最后是不要提前对职位建立太多期待和想象。

2017 年我从扬州大学对面的大专毕业,在家待业五年后,终于没有钱再支撑下去。于是去年十一月开始正式找工作,十二月底拿到第一个 offer。今年年初来到上海,开始了第一份全职工作。

我一直把去某个公司上班看作是一个备选项。这几年经常幻想能写出一本畅销书,或是做出某个创业项目,然后就可以发财一直自由下去。但是基于钱出发的事情都不太有趣,基于兴趣出发做的事情又做得太多,所以钱越来越少,关于收入的焦虑感越来越强,最终只好投降。

个人背景

对于 IT 相关职位来说,我的优劣势大致如下:

劣势

  • 专科学历
  • 土木相关专业
  • 待业五年
  • 零工作经验
  • 技术栈单一(Python/Flask)

优势

  • 技术栈专一(Python/Flask)
  • 参与开源项目的经验(从 2019 年开始做 Flask 的维护者)
  • 一本书(《Flask Web 开发实战》)
  • 一些技术演讲
  • 创建和维护技术社区的经验(HelloFlask
  • 组织技术会议的经验(PyCon China 2019,FlaskCon 2020)
  • 连续三年的微软 MVP 奖项(Python 方向)

blank

从 2016 年实习即回家开始算起的话,我的简历上大概有五年零三个月那么大的空白。不过虽然没工作,这五年也尝试了各种有意思的事情,同时为了获得收入打了一些零工——做了七八个外包项目。

这些外包项目不算优势也不算劣势,但是可以用来填充简历——简历上放了两个开源项目(FlaskAPIFlask)和两个外包项目。而有些劣势也不完全算劣势,比如非科班自学编程,有些 HR/经理会认为不专业,有些则认为这佐证了学习能力和执行力。

求职方向

我对目标职位的三个需求是:

  1. 不加班
  2. 面试不考算法题
  3. 现场(on-site)工作

「不加班」是基本要求,我需要一份正常工时的工作,一来是为身心健康着想,二来是因为我需要有业余时间来写书和做开源项目。

「面试不考算法题」是因为不想浪费时间去刷无聊的算法题。算法题对我来说没有任何乐趣,相比之下,我更喜欢开发 Web 程序和设计 API。

想要一个「现场(on-site)工作」是因为很想去体验办公室生活,顺便体验在不同的城市生活。在家呆了五年后,我也有些厌倦在家工作。太容易过度娱乐和过度工作,模糊生活工作的边界。我想要有一个办公空间来把工作和生活在时间和空间上分隔起来。

国内公司普遍加班,互联网公司普遍考算法题,因此能够满足这三点的只有「非互联网 + 外企」职位。结合我擅长且感兴趣的技术栈(Python Web)和想要去的城市(上海),最终的求职方向是「上海 | 外企 | Python 后端工程师」。

职位搜寻

我在下面这两个地方搜集了 14 个和 Python Web(尤其是 Flask)相关且位于上海的外企职位:

Python 和 Flask 相关的工作还是挺多的,我只收集了上海 on-site 的外企职位,如果扩大范围还可以找到更多。后来我把一些没有来得及投递或已经收到拒信的 Flask 相关职位放到了 GitHub 上。

这两个网站的职位都提供公司网站的招聘链接。我倾向于在公司网站投递简历。虽然没有证据,但我认为这会比在招聘网站上投递更容易被看到。如果招聘网站上直接展示你的资料,比如学历和工作经验,这会降低 HR 打开简历的概率。不过招聘网站可以用来参考薪资范围。

职位投递和面试

我的职位投递策略是只投递自己想去的职位,按照优先级投递,能够拿到一个 offer 就可以。为了把最多的时间投入在优先级更高的职位,我按照意向程度和技术栈匹配程度把这 14 个职位分成了三批。

第一批两个职位在 11 月 20 号左右投递:

  • 育碧:二面挂
  • 博世:口头 offer

第二批四个职位在 12 月 7 号投递:

  • 戴尔 EMC:offer
  • Autodesk:二面挂
  • 万事达:电面通过,后续没有继续面
  • 特斯拉:简历无回复

我统计了每一个职位的时间花销,包括准备面试和面试本身花费的时间。因为不用花时间刷算法题,所以这里的准备主要是:

  • 看出现在职位描述上或是简历技能列表里的相关技术知识,也就是俗称的八股文
  • 练习英语口语,主要是在口语网站上和一些外国人模拟面试对话
  • 了解对应职位和公司,收集相关面经
  • 准备常见非技术问题的回答
  • 准备项目经历介绍
  • 针对每个职位更新简历

育碧

时间花销:22h 21m

  • 11/19 上午官网投递简历
  • 11/19 下午收到约电面时间的邮件
  • 11/25 电面二十分钟,主要聊经历、技术栈和面试安排
  • 11/25 下午收到跳过笔试的邮件
  • 11/26 收到技术面安排邮件
  • 11/30 技术面,一个半小时
  • 12/6 拒信

育碧是一家游戏公司,这可能不应该作为申请职位的主要考量因素,但这的确是最吸引我的一点。哪个喜欢玩游戏的程序员不想去一个游戏公司上班呢?而且入职后还可以免费玩所有的育碧游戏。我把它放到了职位申请列表的最上面。

电面时 HR 告诉我职位对应团队的同事看了我的 GitHub 资料,觉得很惊艳。后续还帮我跳过了笔试环节。不过技术面发挥得一般,有一些算法和 Python 元编程相关的问题没有回答上来。两位面试官在会议室里,声音不是很清晰。

这是我自大学毕业以来的第一次技术面试。在之前的几年里,我有过五六次找工作的经历,大多是朋友推荐,最后因为各种原因不了了之。唯一进入面试的是一个德国的远程工作,因为我的英语水平一般,加上对方有一些口音,所以还没来得及探讨技术话题就匆匆结束了。

博世

时间花销:24h 13m

  • 11/22 中午官网投递简历
  • 11/22 下午接到经理电话,算是电面,聊了经历、技术栈、目标职位的职责,最后约了技术面时间
  • 11/24 技术面
  • 11/25 技术面反馈,布置小作业
  • 12/1 基于小作业的跟进面试
  • 12/2 谈薪资
  • 12/3 口头 offer,协商薪资
  • 中间来回几轮薪资谈判
  • 12/25 HR 回复职位因为疫情推迟招聘到明年二月

博世的职位描述和我的技术栈非常匹配,而且要求看起来很简单。简历处理效率很高,上午投递申请,下午就接到电话。

整个面试过程很顺利。技术面和育碧类似,主要是问 Python/数据库/HTTP/Linux 相关的一些东西。技术面后布置了一个小作业,是实现一个包含特定功能的 Teams bot,给了一周时间。提交作业后的第二天 HR 来谈薪资,再隔一天给了口头 offer。不过 offer 薪资和意向差得很远,我就请 HR 再帮忙协商协商,后来 HR 不知道为什么理解成我拒了 offer。经过几次艰难的谈判后我开始妥协,然而一个月后 HR 回复因为疫情暂停招聘了……

Autodesk

时间花销:13h 25m

  • 12/7 官网投递简历
  • 12/9 下午接到 HR 电话,聊了经历、期望薪资、简单英语对话考察,电话刚挂没多久就收到拒信
  • 12/10 接到另一位 HR 电话,直接约了一面时间
  • 12/13 一面
  • 12/14 HR 约二面
  • 12/15 二面
  • 12/23 拒信

这个职位一开始发生了一些乌龙,后来才明白是因为简历被投递的部门拒了,然后又被另一个部门的经理打捞回来。一面就是经理面,主要聊了我的经历、公司业务和技术栈等等。这位经理很赏识我,整场面试一半时间都在挥动橄榄枝,这给我屡屡失败的面试重新建立了很大的信心。

可惜最终止步于二面,因为有一位面试官对我的稳定性表示担心。二面是技术面,除了一个关于排序算法的问题卡顿了好久才勉强回答,大体表现还不错。

戴尔 EMC

时间花销:10h 2m

  • 12/7 官网投递简历
  • 12/16 接到 HR 电话,介绍面试安排
  • 12/17 连续两场技术面,各一小时
  • 12/22 早上 HR 电话安排终面
  • 12/22 中午终面
  • 12/22 下午 HR 电话谈薪资
  • 12/29 确认薪资和 offer

接到 HR 电话就直接介绍了面试安排,没有聊其他东西。技术面第一场问了很多涉及各个方面的技术问题,还有一段英文对话考察;第二场出了一道简单的算法题,二分查找,不过基于矩阵的变式没做出来。职位描述里除了 Python 和 Flask 还列出了很多我不太熟悉的东西,后来发现这些都没有问。终面是经理面,主要聊一些技术方向、职业规划之类的话题。终面结束后下午就接到 HR 电话谈薪资,29 号确认了 offer。

收到 offer 后非常开心,毕竟是人生第一个 offer,第一时间就开了薯片庆祝:

blank最终拿到 offer 的职位反而是这几个面试里花费时间最少的一个(大部分技术问题相关的准备都已经在前面的面试做得差不多了),也是唯一考了算法题的一个。

万事达

  • 12/7 官网投递简历
  • 12/28 HR 电面,聊经历、期望薪资、简单英语对话考察
  • 1/4 因为已经确认了戴尔 offer,所以取消了后续面试

因为安排太晚,所以没有继续面。后续 HR 说经理对我的简历很感兴趣,问我要不要再聊聊,但我实在不想再折腾面试了。

除了上面这六个主动申请的职位,这段时间还有三个被推荐和邀请的职位,完整参与面试的是下面两个。

Dropbase

时间花销:6h 6m

  • 11/20 收到面试邀请邮件
  • 11/27 一面
  • 12/1 拒信

一个湾区创业公司,技术栈主要是 Python 和 Flask,远程工作。通过 APIFlask 项目找到我。这个职位看起来很不错,不过我当时更偏向找一个 on-site 工作,所以没有花太多时间准备。面试是和两个公司创始人聊天,没有考算法题,一周后收到了拒信。这个职位现在仍在开放,感兴趣的朋友可以试试看。

AWS

时间花销:29h 40m

  • 11/16 内推提交简历
  • 11/17 HR 电面,聊经历、期望薪资
  • 11/23 一面
  • 11/25 拒信

在 AWS 工作的朋友推荐,职位是解决方案架构师,这是我第一次了解到这个职位。30 个小时时间花销大部分是用来准备 Amazon Leadership 和 BQ 问题。一面挂,38 分钟。

备选职位方向:开发者布道师

在十一月底搜集和投递 Python 后端方向的职位之前,我先在开发者布道师(Developer Advocate)方向做了一些零星尝试。这个方向可以申请的职位并不多,而且大多和 Python 没有关系。最终只面了两个职位,均止步于一面。

这个职位的日常工作基本都是我擅长和喜欢做的事情:写作、演讲、分享、教学。如果目标职位的产品和我的技术背景接近的话,我就可以继续在喜欢的主题(Python)产出内容。

一开始是朋友推荐的职位:

  • Nebula Graph:一面挂

面试后我继续申请了几个职位。下面这几个职位除了最后一个都是通过 Google 搜索关键词「Developer Advocate China」找到:

  • TigerGraph:简历无回复
  • JetBrains:一面挂
  • AWS:简历无回复
  • Jina AI:一面后转到后端工程师方向,所以没有继续面

微软

时间花销:22h 30m

第一次了解到开发者布道师这个职位是在四月份,当时微软第一次在国内招聘开发者布道师,朋友推荐我去试试。

我一开始认为自己是非常合适的人选,后来发现这个职位更希望候选人有 Azure、AI 相关的背景(职位名称是 Cloud Advocate 而不是 Developer Advocate)。折腾了很久,最后并没有拿到面试机会。后来微软有一个面向 GitHub & VS Code & Open Source 的开发者布道师职位,看起来更适合我,不过没有在国内开放。

因为我在捕蛇者说一期播客聊到了这件事,所以有朋友推荐了 Nebula Graph 的职位。

Nebula Graph

时间花销:35h 29m

  • 10/12 一面

这是一个面向开源数据库项目 Nebula Graph 的「社区布道师」职位,对我来说是完全陌生的领域,所以有很多准备工作可以做。初次接触后我就迅速下单了两本图数据库相关的书(不过一本看了开头,一本还没拆封)。花了一些时间快速熟悉 Nebula Graph,在这个过程里发现了很多网站、文档、项目上的问题,所以就把这些问题整理了下来(见这篇《Nebula 网站和项目捉虫》)。然后陆续给他们的几个项目提交了一些 PR(代码贡献)。

一面后,我继续提交了一些 PR,作为「如果入职的话会帮忙做哪些改进」的提前展示。不过后面就再也没有收到关于下一轮面试的回复。直到一个月后的某天,HR 提起我上个月的 PR,按照社区规则要给我寄纪念品。微信对话的最后,我问 HR 对上个月的面试有没有什么反馈和建议,但是对方似乎没有看到这条消息。为了打捞学习图数据库沉没的成本,之后我继续投递了 TigerGraph 的布道师职位,结果一沉再沉。

不过没关系,我很快发现了更喜欢的开发者布道师职位——PyCharm Developer Advocate。

JetBrains

时间花销:23h 49m

  • 10/14 官网投递简历
  • 12/3 收到 HR 邮件
  • 12/6 一面
  • 12/22 收到拒信

JetBrains 的 PyCharm Developer Advocate 是这一批开发者布道师方向里最喜欢的职位,因为这和我目前擅长的技术领域一致,我可以继续做和 Flask/Python 相关的事情,不用盖新房子。

十月用 Google 搜索到这个职位,顺手就投递了。中间几次找在 JetBrains 工作的朋友打听,但是一直都没消息。十二月初终于收到 HR 的邮件,约了三天后面试。

收到邮件后,我开始幻想入职这份工作要做些什么,兴奋到很晚才睡着。其实早在申请职位的时候我就已经做了一番规划并注册了 hellopycharm.com。收到回复的第二天,我写了一封表白信放在 hellopycharm.com 上(然后在回复邮件时不经意地提起这个网址):

blank

当时 JetBrains 刚刚在上海成立了分公司,取名捷并思,但我更喜欢「喷气脑」这个名字,所以之后还注册了 penqinao.com,放了一个 logo 在上面:

blank

面试的前几天刚结束另一场英语面试,所以语言问题不大。而且我还在某个英语口语网站上找到同样来自捷克的另一位 Monika 来模拟面试(JetBrains 的 HR 也叫 Monika)。

月底收到拒信说她们希望找到一位有数据科学背景的候选人,不过我在面试时就问过这个问题,她们回答说没关系……

不过还是没关系,对我安慰作用最好的一种说法是,开发者布道师的工作对现在的我来说不是最佳选择。

我在过去几年做演讲和写文章都是跟随自己的兴趣和关注点,如果变成为某个公司的产品/项目——尤其是一个新的领域——做大量的输出,一定没法再像之前那样轻松愉快。另一方面,这类职位的公司也许更想找一位有很多年工作经验、技术栈丰富的人,而我正在找第一份工作,我还只会 Python。

PyCharm 这个职位收到拒信后,我就决定放弃这个职位方向。先做一个后端开发职位会是更好的选择,这样我就可以继续按照自己的喜好演讲和写作,没有任何拘束,而且也有时间踏实学东西,多做积累。

总结

在网络上经常看到有人每天都刷算法题(LeetCode),在无形中制造了一种不刷题找不到工作的紧张气氛。这次找工作才发现不一定需要刷题。有一些公司是不考算法题的,比如大部分非互联网行业的外企和某些创业公司。还有一个 GitHub 仓库记录了所有不需要白板测试(算法题)的公司名单,对应的网站可以用来检索所有不考算法题的开放职位。如果实际工作只是 CRUD,那么实现一个小项目,或是抽象一个公司产品的小功能出来远比考算法题有意义得多。

即使不用刷题,找工作也是一件很累的事情。要承受别人的否定,会认识到自己的局限和不足,然后还有无穷无尽的等待,等待充满随机性的结果。

更糟糕的是,我对每一个投递了申请的公司和职位都建立了太多的期待。除了面经,我还会收集每一个公司的各种信息:公司位置、公司评价、工作环境、周边环境,甚至附近有哪些合适的房子可以租。对于拿到面试机会的两个布道师职位,我都规划了入职后会做什么,具体到可以做的演讲主题、示例程序和教程,并且还提前注册了一些域名。当这些职位收到拒信后,这些期待和规划就全部落空。

经常会觉得自己是某个职位的最佳人选,然后就煞有其事地在晚饭时告诉家人接下来我即将会去哪个城市哪个公司上班……

12 月 22 号到 12 月 28 号是最黑暗的一周。22 号收到 JetBrains 拒信——最喜欢的布道师职位;23 号收到 Autodesk 拒信——最受赏识的职位;25 号博世回复暂停招聘——离 offer 最近的职位。如果没有拿到戴尔的 offer,那就要继续投递第三批职位,经历更多的面试和拒信,想想就后怕。

最后要感谢很多在这段时间提供帮助的朋友们。感谢辛庆老师、思为、清蒸、Aleck、伊洪、Tzu-ping Chung、Joshua Bronson、大妈、琚致远还有其他在 Twitter 和微信上给我推荐工作机会的朋友们;感谢开发者布道师前辈们——Anthony Shaw、思为、朱兴亮和范圣佑提供了很多面试建议;感谢职场前辈张晋涛老师在入职前给我科普了很多职场经验。

同时感谢每一个给我面试机会的 HR 和经理(尤其是戴尔 EMC 的 Fiona 和 Kui),不管我是千里马还是百里马,你们都是我的伯乐。

戴尔 EMC Python/Go 职位内推

内推的最新状态见 greyli.com/dell-jobs。如果你在戴尔招聘网站上发现了其他方向/城市的意向职位,也可以联系我内推。


最近公司又开放了几个新的 Python/Go 职位空缺,如果感兴趣的话,一起来做同事吧。

职位要求:

  • 计算机相关学士学位或 1~2 年软件开发经验(另外还有对应 3~5 年以及 10 年以上经验的职位)
  • 熟悉 Python/Go/Java(任一,最好是 Python/Go 方向)
  • 熟悉 Linux 和 Git 的使用
  • 熟悉 Flask 或其他 Web 框架
  • 有 REST API 开发或微服务相关经验
  • 了解容器和容器编排系统(Docker、Kubernetes、Rancher 等)

加分项:

  • 了解 Angular/React/Vuejs(任一)
  • 了解 MySQL、PostgreSQL 或其他 DBMS
  • 了解或使用过 Jenkins
  • 参与过开源项目
  • 有网络、安全、虚拟化、云平台相关经验

工作地点在上海/成都/台北。工作时间正常,不加班,不打卡,周末双休(965)。混合办公,每周可以最多五天居家办公(不限定时间,在正常工作和沟通的前提下,可以自己安排)。

联系方式:

《Flask 入门教程》第三版发布

最近手里堆积的事情越来越多,两本书的进度被日常工作挤压,于是非常想有一些小小的进展来缓解焦虑。刚好有读者来反馈《Flask 入门教程》不兼容最新版本 Flask 的问题,所以就花了一天时间来更新这个教程。

发布上个版本已经是 2019 年的事情了,这次针对 Flask 最新的 2.1.3 版本做了改写,同时不再兼容 Python 2.7 版本。优化了前面几章的一些内容,后面的章节需要改动的地方不多,就没有认真去更新。另外还顺便用 MkDocs 和 Netlify 把教程重新部署到了 tutorial.helloflask.com 上,后续会废弃掉 GitBook。

过去三年里,这本电子书大概给我带来了五百块的收入(主页上有一个自愿点击的「付费支持¥10」的按钮)。虽然不多,但是时不时收到到账提醒和鼓励的话还是很开心的。感谢每一位付款的读者!

blank

当然,给我带来更大成就感的是看到读者分享他/她通过阅读这个教程写的程序,这是一种给别人带来成就感的成就感——元成就感。

累死的人

每年临近小满的一周时间里,在凌晨两点的苏北农村,每个村子的村口或是某个地方都会有乌泱泱一群人在等车去各处「出蒜」(把蒜从土里拔出来)。这些人大多是四十岁到七十岁、甚至还有八十多岁的中老年人,往年或许还有三十多岁的年轻人,但现在已几乎见不到。

在漆黑的夜里,一辆辆三轮车里挤满了人,他们蜷缩着打着盹,被拉往各处田地。这是村民们一年里少有的能够挣到「大钱」的时候。麦子、水稻和玉米的收获都被收割机包揽,而空有一双手的人,只剩下出蒜、栽稻这两次机会。每年其他时间在各处的杂活,一天能挣五十到一百块,而出蒜一天最少也是两百块起步(蒜的收获赶时节,晚了蒜瓣就会散开)。如果你能干得更快的话,选择包亩而不是包天,每亩甚至能挣到四五百块。

附近村子有位七十多岁的老人,以包亩的方式,一天挣到了九百块。老人很自豪,还遗憾没能凑个整数挣到一千块。但这种自豪和遗憾并没有持续多久。收工回到村子,她下了车没走几步就倒了下去,再没有起来,手里依然还攥着那九百块。九百块,意味着一个人拔了近两亩地的蒜。在三十度的烈日下,坐着或跪着,在地上一点一点挪动,把上万根蒜从地里一一拔出来、甩掉泥土。最后只剩下九百块。

APIFlask 1.0 版本发布

2023/7 Update: APIFlask 2.0 版本有一些变动,详见这篇文章


APIFlask 是一个基于 Flask 和 marshmallow 实现的 API 框架(详细介绍见这篇文章)。经过一年的迭代,终于在这个月初为它发布了 1.0 版本(撒花~)。

blank

1.0 版本主要带来了三个新功能:

  • 支持处理文件上传,新增 File 字段
  • 支持使用外部的认证库
  • 添加了几个新的请求解析位置:json_or_formform_and_files 以及 path

一个 API 变动(breaking change):

  • inputoutputdocauth_required 这四个装饰器移动到了程序实例和蓝本实例上(比如 app.input() / bp.input())。

还有一些代码上的修正和优化,具体可以在变更日志里看到。欢迎更新试用和提交反馈:

$ pip install -U apiflask

在代码之外,也有一些变动和改进:

如果你正在用它开发你的个人项目或是公司项目,欢迎在这里留言告诉我们(我)!

回不去的上海

过完年回到上海的这段时间,陆续凑齐了所有的东西。买了新的床、床垫和衣柜(感谢房东出了 80% 的钱),买了二手的桌子、椅子、台灯、自行车……从家里寄来一些炊具和餐具。从超市买了米、油、鸡蛋和面条。唯独缺一把菜刀。快递不让寄刀,坐火车行李也不让带刀,附近的几个小超市也没找到。来上海后做的第一顿饭,是用勺子切了葱花炒的蛋炒饭(配料是在便利店买的沙拉蔬菜包):

blank

虽然房子空间越来越小,还是缺很多东西,离我完美的上海新生活还差得很远。我想念我的大显示器、键盘鼠标以及各种有用没用的小物件。所以我最终决定在三月的第一个周末回家,把它们带过来。本打算在家呆一周就回来(一周后的车票都买好了),结果一直呆到了现在,侥幸躲过很多次核酸检测和抢菜团购。如果我还在上海,估计会在小区快要被封的时候满大街买刀吧。

回家还有另一件事想做。过年在家的时候,我向身边的亲戚朋友了解了当地在八九十年代的妇女拐卖情况(我家在徐州另一个县的农村)。但是很快假期就结束了,了解到的信息很有限,只在 Twitter 上写了几条推文作为总结。这次回去想深入采访当地农村人口拐卖的事情,写一篇文章出来。因为某些原因,这件事没有做成。

到家的前十四天,我的行程码上有上海的记录,去商场要登记,后来看电影都被要求提供 48 小时核酸证明(就是让我退票的意思)。我如果再晚两周回来,就要享受各种防疫套餐,什么 3+11 啦,7+7 啦,14 天内要做 9 次核酸。

随着上海开始封城,越来越多离谱荒谬的事情发生。每天看着这些信息感到愤怒又无力。这些因为防疫政策而不是病毒本身导致的饥饿、伤害、苦难和死亡是有意义的吗?现在这样混乱、极端的「清零政策」到底是为了什么?没人知道答案。广播里只是一味地重复:让我们众志成城,万众一心,大家吃一点苦,我们迟早会战胜病毒!更加悲哀的是,这些事情在每一个城市都可能发生、已经发生、甚至正在发生。

网络上到处都是煽动仇恨和对立的垃圾文章,比如前一阵那篇国本雄文,看到最后我都恍惚以为文革还没结束。另一方面,求救、揭露现实的文章和评论只会被封禁和删除。连公共媒体都热衷于转发各种意大利英国阴谋论网站的假新闻,你还能指望那些写手们弄出什么正常东西来。

现在仿佛又回到了呆在家里没工作的日子,不知道哪天能回上海。说不定还没有等到回上海那天,就要被封锁在徐州了,对于自己的生活现在谁能说得准呢。

为了薯条、月亮和六便士

前两天偶然翻到《月亮和六便士》的豆瓣条目,看到我刚好在十年前的这一天标记了这本书。当时写下了这条短评:

blank

不知道那位老梆子现在是否还健在?那位像座小山一般、每天在楼道里踱来踱去、以贬低打骂学生为生的教导主任。

我们活着大概就是为了薯条、月亮和六便士。薯条在很远的码头上,而月亮和六便士不过是随时会被没收的东西。而被没收的月亮和六便士,也许我哪天可以拿回来。

如果你在 macOS 上无法访问 Flask 程序

如果你用 macOS 开发 Flask 时无法正常访问程序,或是使用 ngrok 等内网穿透工具时映射的公网地址无法访问,大概率是因为 macOS 新版本(Monterey)的变动导致。你会在页面上看到类似下面的错误信息:

Access to 127.0.0.1 was denied.

You don't have authorization to view this page.

HTTP ERROR 403

或是在执行 flask run 命令时看到类似下面的报错:

OSError: [Errno 48] Address already in use

首先确认你的 macOS 版本是不是 Monterey(左上角 Apple 图标 – About This Mac)或是之后的版本,如果不是那么问题应该和本文无关。

简单来说,新版本的 macOS 上 localhost 5000 端口被一个叫 AirPlay Receiver 的服务占用了。而 Flask 内置服务器默认就运行在 5000 端口,所以会造成端口冲突。当你通过将 host 设为 0.0.0.0 指定 Flask 的内置服务器对外可见,或是使用内网穿透工具时,会发现程序无法访问(有时未设置对外可见也会遇到这个问题)。

最简单的解决方法是关掉这个服务:

  • 系统设置(System Preferences) > 分享(Sharing) > AirPlay Receiver > 取消勾选

或是更改 Flask 开发服务器默认的端口(比如改成 8000)。在执行 flask run 命令时使用 -p/–port 选项可以自定义端口:

$ flask run -p 8000  # 或 flask run --port 8000

或是在执行 flask run 之前通过环境变量 FLASK_RUN_PORT 设置:

$ export FLASK_RUN_PORT=8000 # macOS/Linux
> set FLASK_RUN_PORT=8000 # Windows CMD
> $env:FLASK_RUN_PORT=8000 # Powershell

在 Werkzueg 2.1.0(2022/3/28 发布)版本,如果你执行 flask run –host=0.0.0.0 时检测到了端口被占用,会直接显示相关的错误提示:

$ flask run --host=0.0.0.0
Address already in use
Port 5000 is in use by another program. Either identify and stop that program, or start the server with a different port.
On macOS, try disabling the 'AirPlay Receiver' service from System Preferences -> Sharing.

本文源于去年十一月发的一条推文,最近经常碰见有人遇到这个问题,所以转成这篇文章发出来。

画了一幅涂鸦,送给苹果公司:

blank

2021 年总结

今年一整年都呆在家里。书断断续续地写,但一本也没写完。最后两个月,因为钱花光了,终于下定决心开始找工作,最终在 2021 年最后几天拿到第一份工作的 offer,结束了近五年的自由职业状态。这个 offer 给这一年画上了一个圆满的句号,我也从此跳进这个圈,开始一种稳定循环的新生活。

先从好坏两方面总结今年。

Good

Bad

  • 三个年目标全部落空:两本书都没有写完,APIFlask 也没有发布 1.0 版本
  • PyCon US 2021 演讲议题申请没通过(备选的闪电演讲通过了)
  • 找工作收到拒信若干封

今年尝试了很多新鲜的东西,比如第一次录播客、第一次参加圆桌、第一个英文演讲、第一场足球赛、第一份工作。今年也开始更活跃的使用 Twitter,并且重新捡起来被荒废的 PyCon China 账号。

从下半年开始,经常感觉很焦虑。一方面是因为写书进度缓慢,不知不觉一年又已经过半。另一方面是因为收入——今年拿到的稿费很少,加上不想浪费时间做外包,因此收入锐减。既没有挣到钱,也没有做成事,在这些压力下常常心情也不好,所以自觉失败。

时间记录

今年没有再完整的记录时间花销,去年一年的实验已经让我了解自己的时间花销情况。再继续意义不大,一来记录本身就会浪费很多时间,二来过于追求效率和生产力会让人感到疲惫。因此这一年只记录了一些重要的活动分类。

总记录时间一共 1815 小时(约占全年时间的 20%),其中前三项分别是:

  • 开源项目:535h 50m
  • 找工作:204h 37m
  • 游戏:200h 55m

完整的数据如下:

blank

开源项目时间基本都集中在年初,当时花了几个月时间开发 APIFlask。年中 Flask 2.0 发布后帮忙修了几个 bug,年底给 Bootstrap-Flask 发布了支持 Bootstrap 5 2.0 版本。

找工作集中在最后两个月,不过投入时间最多的几个职位都没有拿到 offer。晚点会在另外一篇文章详细记录找工作的经历和感想。

游戏时间大部分花在了最后一个月开始玩的《塞尔达传说:荒野之息》。这个游戏在年初就和 Switch 一起买了,因为怕花掉太多时间一直没有玩。在找工作等待面试答复的漫长煎熬过程中,什么事情都不想做,所以躲到游戏里。

时间花销排在第六位的写书,本来应该是我的主业。之前完成两本书的阻力很多,比如要解决收入问题,要整理第一版的旧文件排版,还要完善 APIFlask 并发布 1.0 版本。而目前来说,完成它们的最大阻力则是时间太少。工作之后,除了周末两天,每天只有下班后六点到十一点这个时间段才能做自己的事情。再去掉吃饭时间以及偶尔的散步、看电影、玩游戏、做开源项目……不过好在我可以在这个时间段专心做事,没有收入焦虑。

时间花销排在最后的是阅读。今年又没读什么书,记录在案的阅读时间只有 55 分钟……想想大概是在读《非暴力沟通》,不过读了个开头就用来垫枕头了。枕了那么久,也许会吸收到一点点灵气吧。

新年目标

因为 2021 年的三个年目标一个也没完成,所以 2022 年仍然是这三个:

戴尔恶魔城居民+1

一周前来到上海,今天顺利入职戴尔 EMC(别名恶魔城),我的找工作历程至此终于完结了。对新工作和新生活充满期待。

blank

来到上海找了三天房子,最终选了一个离公司 483 米、在意向清单里价格最高的房子。公司周围都是三十多年房龄的破旧小区,一室的价格应该够在家乡县城租七室三厅。好处是离体育场(江湾体育场)和商场(五角场)也只有五百米上下,有很多好吃好玩的地方。

第一次在公司上班,到处都很新鲜,不过第一天不太好意思到处闲逛。中午和同事们一起吃饭散步,感觉像是回到上学的时候。今天帮助我入职的 buddy 是我的读者,不过他今天在家办公并没有来(失职的入职 buddy)……其他同事还把我的书从他的工位拿过来「指认作者」,哈哈。

说到这本书,自然就想起来第二版的截稿日期就快到了,心情突然沉重。各位潜在的读者稍安勿躁,明早起床就开始写书!