我以前曾学过 Python, 但用得不算多, 后来有几年完全没有使用 Python, 现在已经忘得差不多了. 趁着这次重新使用 Python, 顺便把这个 "复习+学习" 的过程记录下来, 也许以后自己回头看也有用.
因此, 复习的时候, 我首先就找变量作用域的教程来看, 主要搞懂 nonlocal 和 global 就可以了, 不需要研究得太深, 遇到问题再研究.
如何引用 (import), 以及怎样组织代码 (packages and sub-packages), 也是了解个大概就可以了.
受到 Go 的影响 (最近几年我用 Go 比较多), 我会尽量不去使用 "继承" 的特性, 但 class 对于更有条理地组织代码是很有帮助的.
同样是 Go 的影响, 我寻找类似 interface 的东西, 找到了 Abstract Base Classes, 另外再了解 classmethod 与 staticmethod 这两个重要概念, 我认为暂时就够用了.
这次我用 Python, 是想写一个可以轻松写插件的文件 /文件夹操作工具, 是个纯命令行程序, 并且用 YAML 或 TOML 来方便用户输入参数.
在实际动手写程序之前, 我习惯先找一下相关的库, 确定项目的可行性, 如果找不到相关的库, 或者看起来很不好用, 我就要考虑换语言了.
结果找到 importlib, Click, tomli 等, 看起来都很不错.
以前我写程序不考虑发布出去给别人用, 但后来 GitHub 流行了, 恰巧用 Go 写的软件只需要发布在 GitHub 即可, 我就顺便发布了. 因此现在写程序已经习惯了考虑如何发布.
Python 程序的发布中心是 pypi.org, 为了避免用户名或程序名与别人冲突, 到时写好程序才发现可能就要改名, 因此我先去 pypi 注册.
发布到 pypi.org 的程序必须有正确的目录结构, 以及一些配置文件 (比如项目名称, 版本号等), 在这里有详细说明 https://packaging.python.org/tutorials/packaging-projects/
另外找到一个帮助打包的好东西 https://github.com/pypa/flit
对于 Python 来说,虚拟环境非常重要,因此 Python 里有很多工具帮助解决这个问题,官方也提供了工具。一般来说,官方的工具就够用了,详见官方文档 https://packaging.python.org/en/latest/guides/installing-using-pip-and-virtual-environments/
如果需要更丰富的功能,推荐使用 miniconda 或 pyenv
有的 Python 程序当作一个库来使用,那就正常写程序就行,而如果要当作一个命令行程序来运行,可采用这种方法 https://click.palletsprojects.com/en/8.0.x/setuptools/#setuptools-integration
采用这个方法时要注意两点:
采用上述方法后,可在项目根目录用命令 pip install --editable .
或 flit install
进行本地安装,只需要本地安装一次,修改代码无需再次安装。
还是受到 Go 的影响, Go 从一开始就强调代码格式化的重要性并且官方自带 formatter (当然, 只是说我受到 Go 的影响, 事实上各种语言都很重视这方面的工具), 很高兴在 Python 这边也找到了优秀的工具: Black, Flake8, Mypy, Pylance
其实我写 Python 并不是太刻意追求类型安全,我决定用 type hints 最主要的目的是可以少写文档、更清晰地写文档。注明参数的类型时,用人类语言太麻烦,还不如用 type hints 更简明。
Mypy 容易安装容易使用,但默认行为不够严格,我没去研究如何提高 mypy 的严格程度,改用 Pylance, 在 VS Code 里设置 type checking mode 从 off 改为 basic 后发现严格程度刚刚好(如果改为 strict 则太严格),因此就这样用了。
到了正式开始编程,倒没什么特别要说的了,源代码的更新记录包含了一切细节。
ffe 是我第一次发布到 pypi 的软件,主要用途是管理自己日常写的零散脚本。最近升级到版本 v0.1.1, 新增了 use_pipe
参数方便多个任务串联。
使用命令 ffe dump -r mimi
可以获得插件 mimi 的 toml 文件:
[[tasks]]
recipe = "mimi"
names = []
[tasks.options]
suffix = ".mimi"
overwrite = false
采用同样的方法获得别的插件的 toml 文件,然后复制黏贴到同一个文件里,例如:
[[tasks]]
recipe = "mimi" # 第一个任务:加密
names = [
'file.txt',
]
[tasks.options]
suffix = ".mimi"
overwrite = false
[[tasks]]
recipe = "anon" # 第二个任务:匿名上传
names = [] # 第二个任务既可指定具体文件名,也可接受上一个任务的结果
[tasks.options]
auto_copy = true
key = ""
use_pipe = true # 设为 true 表示接受上一个任务的结果
然后使用命令 ffe run -f mimi-anon.toml
即可依次执行任务。第一个任务加密后会生成文件 file.txt.mimi, 并把这个文件名传给第二个任务。
如果想使用同一个流程来处理另一个文件,不需要任何改动,只要使用命令 ffe run -f mimi-anon.toml file2.txt
即可对 file2.txt 进行加密和上传。
如果有一些文件需要经常加密上传,这个任务组合就很方便了。还可以把打包压缩、删除文件等任务都添加进去,这比 GUI 工具更灵活,编辑 TOML 文件也很直观。
(关于我写的加密插件 mimi 的安全性在这里 https://v2ex.com/t/827768 有很充分的讨论)
(关于匿名上传的插件的说明详见这里 https://github.com/ahui2016/ffe/blob/main/docs/anon-ibm.md )
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.