怎样编写实用小工具

本帖最后由 wdscxsj 于 2022-9-1 17:52 编辑

[md]最近对 Python 感兴趣的坛友好像挺多,刚才写了个短文,提供一点实践思路,供大家参考。楼下的PDF版有代码高亮,可能更易读。

# 怎样编写实用小工具

## 编程干啥

会编程的一大好处是**让电脑替你做事**。但是初学者限于所见,经常想不出有用的需求,弄几下就凉了,自己也很不满意。

有用的软件应该是**活的**,输入不同的要求都能得出有效的结果。比如最常见的记事本,可以任意写,随便保存。再比如计算器,加减乘除样样行。这些常用软件看似平凡,实际代表了不同方向的几大类需求。

自己编写的实用小工具,可以针对日常使用电脑的频繁操作,想办法把它自动化。有了这个底子,以后的学习工作中遇到问题,自然而然就能想到需要编写(或者寻找)怎样的辅助性工具,提高效率。

**动脑想**是构造合理的需求、提出方案,**动手做**是一步步完成目标,需要不断改进方案、评估工作量、确保质量,二者都很重要。

作为示例,下面简述一个小工具的实现过程。因为没什么技术难度,也为了节约篇幅,主要是指出一些值得思考的地方,看看它是怎样从模糊的“我想要”逐渐具体化的。代码以 Python 为例。

## 初始构想

随便一台经常使用的电脑,应该都保存了很多资料。多到漫山遍野,还在不断增加,但是反复用到的也就几十个。

要是它们整整齐齐该有多好啊!但打死我也不会去整理的……就算拼死弄好了,再放东西还不是慢慢变乱?

我想要一个……会按我心意归类文件的电脑?而且想找啥会自动蹦出来?所以要先研究人工智能和脑机?

太不切实际啦。

那,一个**靠谱的需求**其实是,我把常用的那几十个文件整理出来,也不用把它们放一堆,只要弄个小工具,想用哪个自动替我打开就好。以后有常用的就增加,不再常用的就删掉。

有没有现成的呢?Everything 是搜文件的利器,但是需要写文件名,切输入法。Clavier 之类的可以配置,但有点麻烦。有不少自称神器的,界面整得花花,纯属大炮打蚊子,还不知道会不会偷我数据。机智一点可以维护一堆快捷方式,但是文件一改哪个不对也不容易检查。

**易配置、易调用、跨平台、改细节**。在一个具体需求面前,很多“成熟软件”用这四个显微镜一看,经常不如自己写的一个小脚本好用。

## 先弄原型

我要写个工具,叫它 qo(Quickly Open)。如果想看《三国志》,可以 Win+R 一下,输入 `qo sgz` 回车,就给我打开。

这个嘛,其实很好办:

```py

import os

import sys

mydocs = {

'sgz': r'C:\Books\史\二十四史\三国志.陈寿撰 裴松之注.2011.pdf',

# 其它...

}

def main():

for name in sys.argv[1:]:

path = mydocs.get(name)

if path:

os.startfile(path)

if __name__ == '__main__':

main()

```

其中省略了不少细节,比如没输对的名字应该适当提示,不存在的文件也要有反馈等等。但作为“快速打开”的小工具,这就能用了。

然后把它放在环境变量 PATH 下的一个文件夹里,建议新建一个放在末尾(不明白这句话就查一下)。但是“运行”对话框不能不带扩展名直接运行 .py 文件,所以最好是另写一个 qo.bat,放在 PATH 文件夹里,这是一个常用技巧:

```bat

"path\to\python.exe" "path\to\qo.py" %*

```

试一下确实很方便。

qo 用一个 dict 管理了所有助记名和文件路径,有这个名字就打开。它的好处是,助记名可以自己起,而且配置很直观,不满意随时改。

## 持续改进

名字再好记,多了总会忘。能给点提示多好?比如 `qo -l` 就列出所有助记名,`qo -L` 就把文件路径也列出来。加了选项,用 `sys.argv` 就显得麻烦了,`argparse` 比较便利。

```py

import argparse

def main():

parser = argparse.ArgumentParser(description='qo: quickly open anything!')

parser.add_argument('-l', action='store_true', help='list mnemonics')

parser.add_argument('-L', action='store_true', help='list mnemonics with file paths')

args = parser.parse_args()

if args.l:

print(' '.join(mydocs.keys()))

return

... # if args.L

```

这个代码仍然只是示意,每个选项对应的功能最好用单独的函数实现。如果不喜欢命令行窗口,可以显示在对话框里。

用着用着,要是有的文件变了怎么办?所以要能校验文件路径是否有效:`qo -v`。

```py

parser.add_argument('-v', action='store_true', help='verify file paths')

...

if args.v:

for name, path in mydocs.items():

if not os.path.isfile(path):

print(f'missing: {name} => {path}')

return

```

自己写的小工具,经常用就会发现,可改进的地方有很多。**越经常用,对别人越有用,活力就越大,说明越成功**。持续改进,它就活得更健康。

比如,`-l` 和 `-L` 选项只列出全部就有点浪费了,一般不想看一大堆输出。可以让它们接受一个可选的搜索参数,匹配的才列出来。还可以加一个选项,支持正则表达式匹配。

如果文件名比较长,匹配的部分不容易一眼看出来。可以用 colorama 这个第三方库高亮显示。

`os.startfile()` 相当于双击打开。如果有的文件不想用关联的程序打开,或者需要指定运行参数,就可以把 `mydocs` 拆开管理。

```py

import subprocess

rundocs = {

'name1': ['prog1', 'arg1', 'arg2'],

# ...

}

...

cmd = rundocs.get(name)

if cmd:

subprocess.call(cmd)

```

配置的部分慢慢变长了,继续放在代码里就有点笨重。单独存成配置文件更容易管理,比如 json、yaml 之类的格式,一般放在 home 文件夹里(`os.path.expanduser()`),或者脚本文件的旁边。

如果文件管理的意识比较好,需要快速访问的文件全部放在一个顶层文件夹内,就可以把它配置为“根目录”,其它文件的路径相对它进行计算。这样,只复制这个文件夹就备份了“所有资料”,如果在别的电脑上使用,只修改一个路径(也可以作为命令行选项)就还原了自己熟悉的环境,甚至 Linux 系统也无妨。

实现的功能一多,难免有些边边角角考虑不全,或者后面的把前面的改坏了。所以还应该编写测试代码,确保新功能正确严谨,每次的修改都基础稳固。

以上种种,是成品软件不容易精确提供的,自己实现起来并不困难,又很实用,非常划算。工具虽小,从需求到实现是个完整流程,可以喻大。电脑是游戏机、纯消费品、不务正业,这种观念已经远远落后于时代。找到了合适的方向,就可以用它形成价值,改进自己的学习和生活。

[/md]

怎样编写实用小工具.pdf

2022-9-1 17:43 上传

点击文件名下载附件

110.84 KB, 下载次数: 985