Python统计List的元素个数

以下两端代码,都可以实现。

Counter虽然强,但是数据量大的时候会比较慢。

自己写的轮子:

1
2
3
4
>>> test = [1, 2, 3, 4, 2, 2, 3, 1, 4, 4, 4]
>>> d = {k:test.count(k) for k in set(test)}
>>> d
{1: 2, 2: 3, 3: 2, 4: 4}

collectionsCounter 方法:

1
2
3
>>> from collections import Counter
>>> Counter(test)
Counter({4: 4, 2: 3, 1: 2, 3: 2})

水一贴测试下 Vercel 的自动脚本。

目前本站已经改为 Vercel 托管。coding 卖给腾讯后,页面托管那叫一个蛋痛……

Share下自己编译的 SumatraPDF 绿色汉化优化版

SumatraPDF

SumatraPDF, 开源,免费,多功能,小巧的PDF阅读器(当然,也支持很多流行书籍格式,诸如epub/Mobi/CHM)等等。

已经用了多年了。非常好用,不到6M的体积启动速度完爆各类浏览器。

不过,这个工具的绿色模式(aka,Portable)有个缺点,配置文件和缓存都会放到执行程序目录下。可是,哥习惯把一堆小型程序扔到一个OneDrive目录里面(是的,我就是 ~/bin 党)。

没办法,自己 Clone 下库,然后哼哧哼哧下载VS2019社区版。动手改造下。

(看代码+修改10分钟,搞定编译错误和链接问题20分钟,Clone代码半小时,下载VS2019两个小时……)

改造并不麻烦,见下:

继续阅读···

Python的Bool操作符--奇怪的逻辑但很有用

经常看到下面代码:

1
user_name = form['username'] or 'unknown'

一般来说,or操作符应该返回 bool类型。也就是说,上文代码的user_name 应该是 True 或者 False

php/perl用这种代码多的是,我能理解:

1
foo(bar) or die;

问题是,php/perl不能这么赋值啊……

python的这个逻辑还真挺诡异的……(是的,这种感慨一般来自c/c++程序员,我们较真)。

今日,又看到了类似代码。nnd,查查看。

于是,我得到了这个:

(Note that neither “and” nor “or” restrict the value and type they
return to “False” and “True”, but rather return the last evaluated
argument. This is sometimes useful, e.g., if “s” is a string that
should be replaced by a default value if it is empty, the expression
“s or ‘foo’” yields the desired value. Because “not” has to invent a
value anyway, it does not bother to return a value of the same type as
its argument, so e.g., “not ‘foo’” yields “False”, not “‘’”.)

确实灵活了,也符合人的第一感觉。但是……nnd,一个判断把类型换了到底是什么鬼啊……

不过,话说回来,用的时候……真香……虽然是今日查的,但是我已经用了N久了

就这样,水这么一贴是因为刚刚从半死不活的coding中换了blog服务器。测试下。

V2ray配置前置代理/代理链/链式代理转发

最近需要配置长连接跳板主机。大概的topology是这样的:

主要原因就是防火墙右侧主机设置了白名单,而左侧的服务器创建加密信道穿过防火墙,符合右侧服务器的白名单机制。

VPN配置很麻烦,而且很多国内地区禁用了VPN服务。

所以,用V2ray会简单很多。

V2ray的原理如下:

大概就是,用户主机通过SSR类型的前置代理链接左侧服务器,然后左侧服务器将流量通过VMess协议转发给防火墙右侧服务器。

配置如下:

继续阅读···

Process Substitution---Bash进程替换使用教程

故事起源一次不太愉快的运维面试:

1
2
3
4
5
6
7
8
Me: 一个巨型日志文件,如何一次性统计总行数,包含关键字error和warning的行数?
He: cat log | wc -l; cat log | grep error | wc-l; cat log | grep warning | wc -l
Me: .... , 这不算一次性啊,提示下,tee
He: .... , tee 只支持文件啊...
Me: cat log | tee >(wc -l) >(grep error| wc -l | awk '{printf "error is %s\n",$1}' ) >(grep warning | wc -l awk '{printf "warning is %s\n",$1}') | tee
He: cat log | tee >(...) >(...) 是什么诡异语法?
Me: 传说中的Process substitution啊,blablabla
He: ....

He同学吐槽了我司的奇葩需求后,拂袖而去。当然,主因是我司无法担负期望薪资…

那么,大才He同学不是很明白的诡异语法到底是啥?这里开贴解释一二。

吐槽一下,虽然各路大才都对 *nix下的万物皆文件的理念表示激赏。但真摸清楚文件/文件描述/管道/等基本概念的,还真没几个……

Process Substitution的详细解释,参看 wikimedia 。实际上,认真看完并深入理解后,就可以直接关闭本页。

当然,对这个都没啥很正规中文翻译的feature希望有个快速理解和人话白话理解的话,请继续阅读。

继续阅读···

Win10 Shell的快捷访问方式--Shell:

Windows 10 里面,在地址栏, 运行 等shell输入口里面,可以执行一些shell(explore)的快速内置指令。

一般利用:

1
shell:`command`

从网上查到了这个的全指令。这对键盘党还是很有用的。

顺便说一下,shell:::{2559a1f3-21d7-11d4-bdaf-00c04f60b9f0} 指令就是 打开运行窗口。这个蛮有趣的。

全指令如下:

继续阅读···

Python的多条件排序 -- 基于Tuple大小比较的语法糖

看到了个比较有趣的帖子,是关于Python列表排序的,参看:知乎的这个帖子

例子不难:

1
2
3
4
5
# 列表排序:先按照正负排序,再按照其绝对值排序
a = [1, -2, 10, -12, -4, -5, 9, 2]
a.sort(key=lambda x: (x < 0, abs(x)))
[1, 2, 9, 10, -2, -4, -5, -12]

其中,诡异的就是作为key的lambda函数了。

1
key=lambda x: (x < 0, abs(x))

一个返回tuple的函数,作为key,就可以实现多级排序。什么鬼?!

仔细查了下文档,发现原理是tuple的大小比较……

继续阅读···

Autossh for systemd --- ssh隧道自动加载

autossh 其实是一个ssh的扩展工具。一般应用在ssh 隧道建立/维护中。兼容全部ssh标准指令。可以自动重连服务。

不过,autossh不自带systemd的脚本。这里是修改的一套。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[Unit]
Description=Keeps an ssh tunnel
After=network-online.target ssh.service
[Service]
User=xxx
RestartSec=3
Restart=always
ExecStart=/usr/bin/autossh -v -nNT -R x.x.x.x:29528:localhost:29527 x.x.x.x
TimeoutStopSec=10
[Install]
WantedBy=multi-user.target

复制到:

1
/etc/systemd/system/autossh.service

使用systemctl控制

1
2
3
sudo systemctl daemon-reload
sudo systemctl start autossh
sudo systemctl status autossh

参考的脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[Unit]
Description=Keeps an ssh tunnel to %I open
After=network-online.target ssh.service
[Service]
User=tunnel
# no monitoring
Environment="AUTOSSH_PORT=0"
# Disable gatetime behaviour
Environment="AUTOSSH_GATETIME=0"
EnvironmentFile=/etc/default/autossh@%i
RestartSec=3
Restart=always
# -NT Just open the connection and do nothing (not interactive, no tty alloc)
# use /usr/bin/ssh instead of autossh is good as well
ExecStart=/usr/bin/autossh -NT -o "ExitOnForwardFailure=yes" $SSH_OPTIONS ${TARGET_HOST} $FORWARDS
TimeoutStopSec=10
[Install]
WantedBy=multi-user.target