晨曦's Blog

This is a window to the soul

前记

初次接触 Sanic 框架,在使用的过程中,并没有在文档中发现如何使用应用上下文

使用

通过 issues 咨询后记录如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from sanic import Sanic
from sanic.response import text

app = Sanic('jakehu')

# 应用上下文
app.ctx.db = "msyql://..."

@app.get("/")
async def hello_world(request):
# 使用应用上下文
print(request.app.ctx)
return text("Hello, world.")

app.run(debug=True,auto_reload=True)

参考


题外话:
申明全局的 Json 序列化函数

1
2
from orjson import dumps
app = Sanic('jakehu', dumps=dumps)

前记

鉴于 brew uninstall 只会卸载软件包本身而不会卸载其依赖包,所以我们用 homebrew-rmtree 来解决完全卸载

homebrew-rmtree

安装

brew tap beeftornado/rmtree

使用

1
2
brew rmtree pyenv-virtualenv
brew cleanup

效果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
brew rmtree pyenv-virtualenv
==> Examining installed formulae required by pyenv-virtualenv...
| 3 / 5

Can safely be removed
----------------------
pyenv-virtualenv
pyenv
autoconf
pkg-config

Proceed?[y/N]: y
==> Cleaning up packages safe to remove

Uninstalling /usr/local/Cellar/pyenv-virtualenv/1.1.5... (22 files, 65.4KB)
Uninstalling /usr/local/Cellar/pyenv/2.0.0... (756 files, 2.6MB)
Removing: /usr/local/Cellar/autoconf/2.69... (67 files, 3.0MB)
Uninstalling /usr/local/Cellar/autoconf/2.71... (71 files, 3.2MB)
Uninstalling /usr/local/Cellar/pkg-config/0.29.2_3... (11 files, 623.7KB)

介绍

pyenvPython 版本管理工具。pyenv 可以改变全局的 Python 版本,在系统中安装多个版本 Python,设置目录级别的 Python 版本,还能创建和管理 virtual python environments

安装

利用 pyenv-installer 安装

1
curl https://pyenv.run | bash

安装后会自动安装如下插件
pyenv-doctor pyenv-installer pyenv-update pyenv-virtualenv pyenv-which-ext python-build
~/.zshrc 中添加如下配置

1
2
3
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init --path)"

命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# 查看可以安装的包和版本
$ pyenv install -l

# 安装3.9.5
$ pyenv install 3.9.5

# 创建可执行文件的shims
$ pyenv rehash

# 查看已安装的版本
$ pyenv versions

# 设置全局的Python版本,版本号写入 ~/.pyenv/version
$ pyenv global 3.9.5

# 设置本地的Python版本,版本号写入前目录下的 .python-version
$ pyenv local 3.9.5

# 卸载python版本
$ pyenv uninstall {版本号}

# 列出所有虚拟环境
$ pyenv virtualenvs

# 创建一个3.9.5版本的虚拟环境
$ pyenv virtualenv 3.9.5 V395

# 激活虚拟环境
$ pyenv activate V395

# 关闭虚拟环境
$ pyenv deactivate V395

# 删除虚拟环境
$ pyenv uninstall V395

使用

比如我们现在有一个场景,为 sanic 项目创建一个虚拟环境
第一步:
我们需要安装需要的 Python 版本比如 3.9.5
pyenv install 3.9.5
第二步:
创建一个 3.9.5 版本的虚拟环境
pyenv virtualenv 3.9.5 sanic
第三步:
去到 sanic 项目目录
pyenv local sanic
第四步
取消设定
pyenv local --unset
第五步
导出 requirements.txt
pip freeze > requirements.txt


到这里就可以在 sanic 项目下愉快的玩耍了

前记

当我们需要统计累积量的时候就需要计算同一业务以及相邻两行的差值

业务

接下来我们模拟一个业务,就是统计每天数据表的行数增加量。首先我们需要每天将当天表的数据行数写入到数据库

表结构如下:

1
2
3
4
5
6
7
8
9
CREATE TABLE `table_logs` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`table_name` char(64) NOT NULL DEFAULT '_' COMMENT 'table_name',
`row_num` bigint(20) NOT NULL DEFAULT 0 COMMENT '行数',
`created_at` datetime NOT NULL DEFAULT current_timestamp() COMMENT '创建时间',
`updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
PRIMARY KEY (`id`),
KEY `uuid` (`uuid`),
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8

实现

方法:t1.rownum = t2.rownum - 1

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
SELECT * FROM
(
SELECT
(@rownum := @rownum + 1) AS rownum,
`id`,
`table_name`,
`row_num`
FROM
table_logs,
(SELECT @rownum := 0) t
WHERE
1 = 1
ORDER BY
`table_name` desc, `id` desc
) as t1
LEFT JOIN (
SELECT
(@INDEX := @INDEX + 1) AS rownum,
`id`,
`table_name`,
`row_num`
FROM
table_logs,
(SELECT @rownum := 0) t
WHERE
1 = 1
ORDER BY
`table_name` desc, `id` desc
) as t2 on t1.rownum = t2.rownum - 1 and t1.table_name = t2.table_name

最后只需要将 t1.row_num-t2.row_num 就可以实现我们的需求

前记

Python 中使用 json.dumps 时出现 xxx is not JSON serializable

问题一

1
TypeError: Object of type Decimal is not JSON serializable

问题二

1
TypeError: Object of type datetime is not JSON serializable

解决

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import datetime
import decimal

class JSONEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, decimal.Decimal):
return float(obj)
if isinstance(obj, datetime.datetime):
return obj.strftime('%Y-%m-%d %H:%M:%S')
if isinstance(obj, date):
return obj.strftime("%Y-%m-%d")
return json.JSONEncoder.default(self, obj)

json.dumps(data, cls=JSONEncoder)

JSONEncoder 中的类型可以扩展,加上自己需要的类型即可

需求

Vue 中需要对 Table 数据进行多选,且翻页时需要对前一页选中进行保留

代码

HTML

1
2
3
4
5
6
7
8
9
<el-table
:data="data" border highlight-current-row
@selection-change="handleSelectionChange"
:row-key="getRowKeys"
ref="selectionTable">
<el-table-column type="selection" :reserve-selection="true">
</el-table-column>
...
</el-table>

JS

1
2
3
4
5
6
7
8
9
// 当选择时调用
handleSelectionChange(val) {
// 业务处理
},
getRowKeys(row) {
return row.id; // 重点是id不能重复
},
// 清除所选,视情况在所需要的地方调用即可
this.$refs.selectionTable.clearSelection();

重点是:row-key 不能重复,也就是 getRowKeys 中的 ID 不能重复

前记

业务需求,在 Vue 表格中需要是实现一件展开与一键折叠

代码

HTML

1
2
3
4
5
6
7
8
9
<el-form>
<el-form-item>
<el-button type="primary" @click="handleExpand">{{expandText}}</el-button>
</el-form-item>
</el-form>

<el-table ref="multipleTable" :data="data" border highlight-current-row>
...
</el-table>

JS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
export default {
data() {
return {
isExpand:false,
expandText:"一键展开",
};
},
methods: {
handleExpand() {
this.isExpand = !this.isExpand
this.$nextTick(() => {
this.forArr(this.data, this.isExpand)
})
if (this.isExpand === true) {
this.expandText = '一键折叠'
}
if (this.isExpand === false) {
this.expandText = '一键展开'
}
},
// 遍历
forArr(arr, isExpand) {
arr.forEach(i => {
// 用于可展开表格与树形表格,切换某一行的展开状态,如果使用了第二个参数,则是设置这一行展开与否(expanded 为 true 则展开)
this.$refs.multipleTable.toggleRowExpansion(i, isExpand)
if (i.children) {
this.forArr(i.children, isExpand)
}
})
},
}
};

效果



Vue 中通过 Key 值的改变进行新的渲染,如:key="变量名" 通过修改变量的值可以重新渲染组件

grep 过滤注释行和空白行

cat /etc/kibana/kibana.yml | grep "^\s*[^# \t].*$"

grep 查看非系统进程

ps -ef | grep -v ]$

Bash 脚本错误处理

1
2
3
4
5
6
# 写法一
set -euxo pipefail

# 写法二
set -eux
set -o pipefail

参考

前记

bitwarden_rs 一直是安装在群晖上的 Docker 中的,对外访问也是通过群晖应用门户程序->反向代理反向代理加路由器端口转发

但是有一个问题,就是群晖 UI 界面的反代没有办法编辑配置,也就没有办法利用 bitwarden_rsWebSocket 自动推送更新

解决

想到的解决方案有两个,第一是通过 Docker 再装一个 Nginx 来做反代,第二是通过群晖自身的 Nginx 来做反代;最后选择了通过自身 Nginx 来做反代

Nginx 配置

/usr/syno/etc/certificate/system/default/ 为群晖安全性->证书上传的默认证书的存储位置

8888、3012 端口为 bitwarden_rs80、3012 映射到群晖对应的端口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name xxx.com;

ssl_certificate /usr/syno/etc/certificate/system/default/fullchain.pem;
ssl_certificate_key /usr/syno/etc/certificate/system/default/privkey.pem;

#ssl_session_cache shared:SSL:50m;
ssl_session_timeout 4h;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_buffer_size 4k;

if ($scheme = http) {
return 301 https://$host$request_uri;
}

location / {
proxy_pass http://127.0.0.1:8888;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect http:// https://;
}

# bw WebSockets
location /notifications/hub {
proxy_pass http://127.0.0.1:3012;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}

# bw WebSockets
location /notifications/hub/negotiate {
proxy_pass http://127.0.0.1:8888;
}

error_page 403 404 500 502 503 504 @error_page;

location @error_page {
root /usr/syno/share/nginx;
rewrite (.*) /error.html break;
allow all;
}
}

链接

将配置文件链接到 /etc/nginx/sites-enabled/
ln -s /volume1/docker/nginx/xxx.com.conf /etc/nginx/sites-enabled/

重启

最后只需要重启 Nginx 即可
sudo synoservicecfg --restart nginx


题外话:

利用第三方 FFMPEG 解码器让群晖的 Video Station 完美支持 DTS、EAC3、TrueHD

参考 01
参考 02

这里指的破解之法为无限期使用 30 天试用期

方法一

卸载重装

方法二

对于 Mac 系统删除以下两个文件即可

1
2
~/Library/Preferences/SmartGit/20.2/preferences.yml
~/Library/Preferences/SmartGit/20.2/license
0%