#743 pipx: 虚拟环境版本的 pip
Python pip pipx 2022-01-13pipx 和 pip 一样,也是来自 PyPA 的项目。
PS: PyPA 的知名项目包括 pipenv, pip, pipx, virtualenv, flit, twine。
pipx 的作用是将包安装在虚拟环境中(利用标准库中的 venv)。用来安装一些 Python 写的工具就很好,不需要关心这些工具的代码时。
coding in a complicated world
pipx 和 pip 一样,也是来自 PyPA 的项目。
PS: PyPA 的知名项目包括 pipenv, pip, pipx, virtualenv, flit, twine。
pipx 的作用是将包安装在虚拟环境中(利用标准库中的 venv)。用来安装一些 Python 写的工具就很好,不需要关心这些工具的代码时。
我研究了半天之后感觉无法掌握 poetry,决定放弃,还是用我的 Pipenv。
Poetry 是一个 Python 虚拟环境管理器。
给 tmuxp 提了一个 Issue, 作者 @tony (Tony 老师?😜) 让我选择是自己写测试,还是他来写。
我表达我对 pytest 不熟之后,他给我一点建议:
所以我先学习学习,然后抽空把 test 自己写了。
相关阅读:Redis 拓展模块,其中用 RedisJSON 举例编译安装。
简单示例 (GET / SET):
127.0.0.1:6379> json.set abc . 123
OK
127.0.0.1:6379> json.get abc .
"123"
127.0.0.1:6379> json.set xyz . '{"a": 1, "b": true, "c": [{"name": "foo"}, {"name": "bar"}]}'
OK
json.get xyz .c[0]
"{\"name\":\"foo\"}"
127.0.0.1:6379> json.set xyz .a 2
OK
127.0.0.1:6379> json.get xyz .c[0].name
"\"foo\""
127.0.0.1:6379> json.set xyz .c[0].name '"loong"'
OK
127.0.0.1:6379> json.get xyz .a .c[0].name
"{\".c[0].name\":\"loong\",\".a\":2}"
现在还没有相关行业标准,RedisJSON 自己实现了一套(v1), 后来参考 JSONPath 语法又重新实现了一遍 (v2)。
至于 v1 和 v2 有什么区分,就不用深究了。
大致知道这样可以就行了:
.store.book[0].title
// 相当于 `V['store']['book'][0]['title']`
arrappend
arrindex
arrinsert
arrlen
arrpop
arrtrim
clear
debug
delete
get
/ jsonget
mget
/ jsonmget
numincrby
nummultby
objkeys
objlen
resp
set
/ jsonset
strappend
strlen
toggle
type
Python 库还有以下两个方法:
set_file(name, path, file_name, nx=False, xx=False, decode_keys=False)
return self.set(name, path, file_content, nx=nx, xx=xx, decode_keys=decode_keys)
1. set_path(json_path, root_folder, nx=False, xx=False, decode_keys=False)
file_path.split('.', 1)[0]
)set_file(file_name, json_path, file_path, nx=nx, xx=xx, decode_keys=decode_keys)
Python 最知名的 Redis 客户端库 redis-py 已经支持 RedisJSON 拓展指令。
import redis
from redis.commands.json import JSON
r = redis.Redis(host='localhost', port=6379, db=0)
jr = JSON(r)
jr.set('foo', '.', {"a": 1, "b": True, "c": [{"name": "foo"}, {"name": "bar"}]})
jr.numincrby('foo', 'a', 1)
jr.toggle('foo', '.b') # only works for booleans
jr.arrappend('foo', '.c', {"name": "air"})
print(jr.get('foo', '.'))
# {'a': 2, 'b': False, 'c': [{'name': 'foo'}, {'name': 'bar'}, {'name': 'air'}]}
print(jr.get('foo', '.c[-1].name'))
# air
就缺搜索了,如果加上 RediSearch,就完美了。
PS: RediSearch 的新版本已经优化了对 JSON 的支持。
Redis 官方其实还提供了以下拓展:
PS: 还有更多第三方拓展,参考 https://redis.io/modules。
Redis 是 BSD 协议,Redis 拓展模块是 AGPL 协议。
2018 年 8 月,为了防止云服务厂商的利益侵害,Redis 拓展模块授权协议切换到 Apache v2.0 modified with Commons Clause (官方声明)。其中 Common Clause 就是限制提供商业的 Reids 服务。
2019 年 2 月,Redis 拓展模块授权协议再次切换,改成 Redis Source Available License (RSAL),(官方声明)。因为认为当前协议不够明确,容易让人产生误解,而且对 Redis 公司的权益保障不到位。
这个协议对普通用户(个人或企业)没有限制,只是限制了直接利用 Redis 服务赚钱的云厂商。我觉得这是开发者的合理诉求,没有什么值得质疑的。
如果只是要体验一下,不想编译,可以去 https://redis.com/redis-enterprise-software/download-center/modules/ 下载试用。
xxx.so
loadmodule xxx.so
,然后重启 Redis 服务--loadmodule
参数动态加载模块。比如 ReJSON:
wget https://github.com/RedisJSON/RedisJSON/archive/refs/tags/v2.0.6.zip -O redisjson-v2.0.6.zip
unzip redisjson-v2.0.6.zip
cd RedisJSON-2.0.6/
# 安装需要用到官网没有提到的 libclang.so
# From: bindgen-0.59.2/src/lib.rs
sudo apt install libclang-dev
cargo build --release
cargo test --features test
# 需要先安装 Rust (请参考其他资料)
# 我了解到的其他模块大多数是 C 写的,RedisJSON 比较特殊,用 Rust 写的
redis-server --loadmodule target/release/librejson.so
相关文章:RedisJSON 体验
西安一码通半个月内两次宕机,值此西安疫情突发之时,可是严重的安全故障。相关负责人(西安大数据资源管理局局长)已经停职检查。
为确保系统运行更高效,他们将一张图片从1MB压缩到500KB,再从500KB优化到100KB。这样的工作看似简单,却蕴含着高技术含量,他们连续两天两夜守在电脑前,终于攻下难关。
维持之前的设定,走技术专家的路线。
第一点,今年会得到改进。
第二点,需要更长时间周期的投入才能见效。
第三点,比较泛,需要更多思考。
第四点,可能是最难的。我不知道该怎么做。
新的一年,岁数又会 +1,在这个一年开始的时候,对过去做个总结,对将来做个展望。
前提:工作习惯养成:1. 计划,2. 重要的事情优先完成,3. 不加班 (上班时间完成工作)
如果按平均每天 2h 来计划,全年有 730h。
个人项目的开发不占用这里的学习时间,另外从周末时间里面挤。
$ ip -c -6 addr show dev wlp6s0
3: wlp6s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
inet6 2409:8a4d:c81:c140::5/128 scope global dynamic noprefixroute
valid_lft 226977sec preferred_lft 140577sec
inet6 2409:8a4d:c81:c140:ca67:f46:7f29:1dad/64 scope global temporary dynamic
valid_lft 376sec preferred_lft 376sec
inet6 2409:8a4d:c81:c140:fcf0:3456:fac4:3b63/64 scope global dynamic mngtmpaddr noprefixroute
valid_lft 376sec preferred_lft 376sec
inet6 fe80::56f8:128b:b513:e571/64 scope link noprefixroute
valid_lft forever preferred_lft forever
# ipconfig /all
# ipconfig
无线局域网适配器 WLAN:
连接特定的 DNS 后缀 . . . . . . . :
IPv6 地址 . . . . . . . . . . . . : 2409:8a4d:c81:c140::6
IPv6 地址 . . . . . . . . . . . . : 2409:8a4d:c81:c140:68cd:b350:9fe8:9feb
临时 IPv6 地址. . . . . . . . . . : 2409:8a4d:c81:c140:757f:88b3:b455:5882
本地链接 IPv6 地址. . . . . . . . : fe80::68cd:b350:9fe8:9feb%5
IPv4 地址 . . . . . . . . . . . . : 192.168.1.7
子网掩码 . . . . . . . . . . . . : 255.255.255.0
默认网关. . . . . . . . . . . . . : fe80::1%5
192.168.1.1
DHCP 服务器 . . . . . . . . . . . : 192.168.1.1
DNS 服务器 . . . . . . . . . . . : 2409:804c:2000:1::1
2409:804c:2000:2::1
192.168.1.1
IPv4 4 字节, 一般用四个十进制的数字表示,xxx.xxx.xxx.xxx
形式,每一段的范围是 0~255。
IPv6 16 字节,一般用 32 个十六进制数表示,每四个一组,共八组,xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx
形式,每一段的范围是 0000~FFFF。
0001
就可以写成 1
fe80::
, ::
(全 0), 又比如上面的 2409:8a4d:c81:c140::5
A:B:0:0:C:D:0:0
不能写成 A:B::C:D::
, 只能缩写成 A:B::C:D:0:0
或 A:B:0:0:C:D::
如果一台机器有多张网卡,都有一个 fe80 的链路地址,操作系统无法区分一个包该走哪张网卡出。
在 IPv4 中,不同网卡一般配置了不同子网,比如 172.16.31.0/24
, 172.168.32.0/24
。
但是 IPv6 的分配可以自己生成(无状态地址自动配置),大家都在 fe80 段。
百分号后面附加的是 zone index,这个数据是操作系统解释的。Windows 会采用接口号(整型数),而 Linux 习惯端口名称,比如 eth0, enp7s0。
PS: 推荐阅读: 网卡名称的变迁(ethX -> enpXsY)
netsh interface ipv6 show address
ifconfig
注意:用在 URL 中时,这个百分号应该转义成 %25
。
IPv4 有分区的概念,一开始叫做分类网络,ABCDE 五类。后来又有无类网络 (Classless Inter-Domain Routing, CIDR),取任意长度作前缀,比如 172.16.0.0/12 以 1010 1100 0001
做前缀。
IPv6 也有分区的概念,和 CIDR 一样,可以取任意长度作前缀。
比如 fe80::/10 就是以 1111 1110 10
做前缀。
移动网络给我分配的是 /64 段,听说有地方能拿到更短前缀(V2EX, 2020/07, 电信 IPv6 大家还能拿到/56 么)。
如果拿到更短前缀,就可以自己在家划分子网了。根据现在的实践(SLAAC),一个网络最少需要留 64 位,如果正好分的是 64 位前缀,那么就不能采用 SLAAC 方案了,只能走 DHCP。
:information_source: See also … Angular
:information_source: See also … AngularJS