关于 Pager

好久没有更新了,最近研究了下如何用 Python 实现 Pager 的功能,这里指的是 Terminal 中的 Paging 程序,比如 less。 Why Pager Pager 在大段文字的展示中很常见,比如 Linux 的 man page,而 $PAGER 就是用来指定默认 Paging 程序的环境变量。Python shell 里面的 help() 会默认翻页显示,IPython 的 ? 则更胜一筹,能够判断当前屏幕的可用空间来决定是否 Paging。 Less 应该算是最流行的 Pager 了,相比于 more,它同时支持前进和后退翻页,而且因为不需要一次性读取整个文件,它的启动速度在打开大型文件时要远远快于 vi。因此,许多 Pager 都是通过启动系统自带的 less 程序来实现。 Don’t Reinvent the Wheel 轮子总是有的,而且还很多,这里说几个比较好用的: Pydoc 的 pager Click 的 echo_via_pager IPython 的 page Pydoc 是 Python 自带的,已经稳定存在了很多年,轻巧好用;Click 的实现类似,而且支持传入一个 generator;IPython 的 page 更加强大,可以自动判断当前的屏幕大小,再结合一个 screen_lines 参数来计算最终的可用空间。 再说说这几个轮子的实现,基本思路都是上面提到的调用系统 Pager。因为要兼容五花八门的操作系统,大致上又分为三种处理方式: 理想情况下是使用 PIPE。因为打开的系统 Pager 必然是子进程,而 PIPE 通过内存中的缓冲区实现了 IPC,这样既不用一次性读取所有数据,后续的 write 操作效率也高。...

04-02 · 2 min

Python 中的闭包

def f1(): l = [] def c(): l.append(1) def f2(): a = 1 def c(): print(a) a = 2 类似 f1 和 f2 中的闭包写法,之前总是在用了前者多次之后,再写后一种就报错,感觉很莫名其妙,明明都差不多。研究了下发现,其实这是 Python 闭包的 BugFeature,理解之后反而觉得这样的设计是合理的。 首先说 Closure,也就是闭包,特指内部的函数及其引用的超出本身作用域的对象,总是在函数嵌套时发生。在 f1 中,c 就是一个闭包函数,同时 l 也算作其中的一部分。因为 c 使用了 l 导致延伸了原有的作用域,所以才有闭包的产生。 再看 f2,如果我们只对 a 做 read 操作是不会引发问题的,由于 c 中尝试了赋值操作,才导致了 UnboundLocalError. 这是因为 Python 解释器会假定函数中赋值的变量是局部变量,而 c 中本身并没有定义 local 的 a 变量;其次,异常在 print(a) 时就会抛出,不会等到 a = 2 的执行。 那为什么 f1 没问题呢,是因为列表为可变对象,append 操作只是更新了里面的内容,并不存在赋值。 def f(): l = [] def c(): l....

01-29 · 1 min

关于 HTTP Auth

Auth 代表了 Authentication 和 Authorization 两个概念,也就是认证与授权。基于 HTTP,两者得以遵循一定的标准,SSL/TLS 之后,又出现了 OAuth 2.0,让授权也简单了许多。 Authentication 认证相对来说比较直接,核心就是对 Credential(e.g. username/password) 的验证。HTTP 提供了多种认证方案,比如最常见的 Basic auth, Digest access 和 Bearer. Basic auth 具体来说就是服务器用 WWW-Authenticate 表示需要认证,比如 WWW-Authenticate: Basic realm='Accessing to xx site',客户端则通过 Authorization 提供相关信息:Authorization: Basic Zm9vOmJhcg==,后面的一串编码是对用户名密码明文进行 base64 的结果,即可以直接从中 decode 出原始信息 foo:bar. 没有 HTTPS 的保护,这样很不安全,所以 Apache/Nginx 对 BA 的实现都会使用密码的哈希结果而不是原文,拿后者举例: http { server { location / { auth_basic "Accessing to xx site"; auth_basic_user_file /path/to/authfile; } } } 然后需要在 authfile 中保存 username/password pair,比如 sudo htpasswd -c /path/to/authfile user1,htpasswd 是 Apache 提供的专门用来生成 BA 使用的 Credential file 的工具。不用额外安装,我们直接用 openssl 代替:...

01-28 · 3 min

Spicks and Specks

Where is the sun That shone on my head The sun in my life It is dead It is dead Where is the light That would play In my streets And where are the friends I could meet I could meet Where are the girls I left far behind The spicks and the specks Of the girls on my mind Where is the sun That shone on my head...

01-20 · 1 min

水浒传之英雄本色

没想到 2021 年的第一篇博客是关于电影的,感觉很奇特。平时看电影最多就是上豆瓣评个分抖两句机灵,这次却想写一整篇,大概对于喜欢的东西废话就会变多吧。 一个好故事 《水浒传之英雄本色》讲述了林冲上梁山之前,和鲁智深相识结义并与朝廷决裂的故事。剧情流畅,引人入胜。 1. 起 开头就是一个小片段,林冲从插翅虎手中救回了高衙内,寥寥几笔便刻画出了林冲的武功和衙内的无赖,也为后来两人之间的矛盾升级埋下了伏笔。 后面又简单描绘了林冲的性格(武痴、不畏权贵)和生活状态(和妻子如胶似漆),平稳之中让人感觉巨变即将来临。 2. 承 这里主要开始写林冲和鲁智深相识相交到结拜成兄弟的过程,我觉得也是整个电影最好看的部分。两个英雄人物的性格碰撞,切磋武功又怕王祖贤饰演的妻子发现,十分欢乐。既有兄弟情义,又有夫妻恩爱。 巧妙的是里面还用武功的隐喻了林冲此时的立场:以退为进。鲁智深劝其罢官上梁山,但他认为只要足够忍让,仕途之路仍然可以走出一片天。 3. 转 与鲁智深告别之后,林冲迎来了人生的暴风雨。狡诈的高俅父子在明,阴险的陆谦在暗,栽赃诬陷,虽有丞相帮助,最后还是免不了发配充军。 探监这里王祖贤换了黑衣,发型也改变了 后面愈加悲惨,妻子被衙内觊觎已久,结果惨死刀下;而林冲自己也险些被手下的兵士所害,幸得结拜大哥及时来救。 在流放的军营里,林冲依然在以退为进,拒绝鲁智深的劝说,甘愿挨饿受罚,对朝廷还抱有幻想。 4. 合 最后,得知丞相妻子皆死,林冲终于下了复仇的决心,但他首先做的是和鲁智深决裂,支走对方,独自面对陆谦大军。这里两人的内心各有表达,林冲自言自语重复了结拜时说的话:有福同享,有祸我当;而鲁智深则把疑问都抛给了坐骑,虽然马儿再三摇头,却还是决然返回:为兄弟,没有面子就没有面子。 结局自然是两人手刃敌人,终于齐上梁山。 英雄本色 越写越觉得一部电影的剧情逻辑和人物形象重要,那个时候的特效很落后,但用几个简单的场景和对话就可以把每个人的性格和内心写活,看起来回味无穷。除了故事本身,整个片子的阵容也超级强大: 主角 林冲:梁家辉的古装扮相极其帅气(发髻加高马尾),和新龙门客栈中的形象不相上下 鲁智深:徐锦江把这个角色塑造地非常到位,还被提名当年金像奖最佳男配角 妻子:一袭白衣的王祖贤绝美,柔情似水的表演让人难以忘怀 反派 高俅父子:老戏骨刘询自不必说,难得的是带胡子的奸人角色(不知道是不是唯一,老爷子一向是有胡子善没胡子奸的);单立文的疯癫演技独树一帜,抛开角色,演员本身还是很正直的(从网上看),还给主题曲作了词 陆谦:林威很适合这种反面形象,在结尾决战的时候几次规整官帽的动作,把陆谦对功名利禄的执念体现得淋漓尽致 客串 仇五:刘青云客串的小角色,为报恩林冲而死,戏份少但很精彩,难怪后来成为影帝 丞相:午马轻松出场两次,每次都会让我想起燕赤霞 其他 导演:陈会毅,港片的武指老炮 配乐:胡伟立,绝对的大师 看完电影的光辉时刻,总是不想跳回生活的平淡点滴,但两者难免要糅和,英雄本色要面对的是漫长人生路的每一天。这部戏还有一点可贵的地方就在于演员自身也是很有性格魅力的人。之前看芒果 TV 的一路成年,梁家辉和徐锦江都是很爱家爱孩子的人,但前者也是时而暴躁的硬汉,而后者身上则充满了艺术家的多愁善感。还有息影多年的王祖贤,自己去买菜的市民刘先生。那个时代的香港影星总是不乏传奇色彩。 资源 爱奇艺上的港片资源不算少,但这部的质量很差。YouTube 有高清的在线版本: 可以用 yt-dlp 下载到本地。 原声带比较好找,QQ 音乐和网易云应该都有现成的资源。 References 水浒传之英雄本色 - 豆瓣

01-14 · 1 min