Python的语法简洁而清晰,具有丰富和强大的类库及第三方库。它能够很轻松地将各种语言模块联结在一起,所以被称为“胶水”语言。当然,Python也能够方便快捷地编写一些常用的工具程序,而用其他程序设计语言需要编写很复杂的代码来完成的功能,通过Python的类库,可能只需要几行代码就能完成同样的功能。
利用Python的这种快速开发特性,在日常计算机维护方面,Python就大有用武之地。可以利用Python语言编写各种系统维护的程序,甚至还可以用它来开发远程维护或监控计算机系统的程序。本章将介绍一些典型的应用场景和实际案例。
20.1 案例背景
Windows用户都有这样的体会,计算机使用一段时间后,感觉速度越来越慢,不但启动时速度变慢,启动后的运行速度也越来越慢。这是因为Windows操作系统在运行过程中会不断地产生垃圾文件,安装、卸载、使用应用程序,也会产生垃圾文件。
这些垃圾文件随着计算机的使用越来越多,如果得不到及时的清理,将会影响到计算机系统的运行速度。既然知道是由于垃圾文件的原因造成计算机速度变慢,那么解决方法也就有了,就是将这些垃圾文件及时清理掉。
清理垃圾文件的方式有多种:
第一种方法,逐个盘符、目录查看是否存在垃圾文件,若有,则删除;
第二种方法,借助一些工具软件,通过这些软件可以轻松地扫描、删除垃圾文件;
第三种方法,利用所学的Python知识,自己编写清理垃圾文件的程序。
这几种方法各有优缺点:
第一种方法由人工去分辨垃圾文件,可以很自由地决定哪些是垃圾文件,但是费时费力,效率很低;
第二种方法省时省力,但其缺点是只能清理该软件认识的垃圾文件,对于一些由特殊软件产生的垃圾文件则无法辨识;
第三种方法是由Python程序去代替人工辨识垃圾文件,当有特殊的文件类别需要清理时,可以通过修改Python程序快速地删除这些文件。因此,这种方式有第一种方法的灵活性,且效率又有很大提高。当然,刚开始编写的清理程序功能不是很完善,需要用户在使用过程中不断提出新需求,逐步完善其功能。
本章的案例主要考虑以下几方面,编写Python程序解决这些问题。
(1)扫描垃圾文件,统计垃圾文件数量及大小;
(2)删除垃圾文件;
(3)扫描计算机中的大文件,并列出指定大小的文件;
(4)查找匹配部分文字名字符的文件。
本章将编写Python程序来解决这些问题。当然,计算机维护还有很多功能,参照本章编写的Python程序,你也可以自己编写代码来解决问题。这样,随着需求不断地增多,最终就可得到一个比较完善的维护计算机的Python程序。
20.2 从创建图形化界面开始
根据上节分析的需求,本章的案例需要完成多项功能,可以将每一项功能单独编写一个Python程序,在使用时分别执行这些程序即可。为了方便使用,最好将这些功能集成在一起,并使用图形化界面。这样,通过单击鼠标就可选择执行相应的功能。
20.2.1 创建基本图形化工作界面
在编写创建GUI的程序之前,要先对需求进行分析,划分出功能模块,如图24.1所示是一种功能模块划分方式。在这个图中,将功能分为“搜索”和“清理”两部分,分别完成搜索文件和清理垃圾文件的功能。另外增加了一个“系统”,主要用来提供退出的功能。(图20.1功能模块划分)
从图20.1所示功能模块划分可看出,PytOptimize需要完成6项工作,功能不算太多,可以考虑在GUI界面中创建6个按钮,每个按钮连接一个功能。但是,这种通过按钮的方式不方便以后扩展,如果以后功能扩展到几十个,显然就不适合使用按钮了。对于功能项很多的程序,最好就是使用菜单。因此,本例也使用菜单来驱动。
注意: 在项目实施前,一般都要事先对程序所要完成的功能进行规划或设计,以便于划分模块或代码,使代码结构清晰,并容易实施代码的编写。
编写以下Python程序,通过使用tkinter模块创建用户界面:
运行以上程序,将显示如图24.2所示的窗口。在窗口上方显示了3个下拉菜单,分别对应图24.1所示的模块。在菜单下方是一个列表框,用来显示最终处理结果,列表框右侧添加了一个垂直滚动条,当列表框中的内容太多时,可通过这个滚动条快速移动。在窗口的最下方还加了一个标签,用来显示当前正在扫描处理的文件。
20.2.2 响应菜单事件
在如图20.2所示窗口中单击选择“系统”→“退出”菜单命令,窗口并不会被关闭。这是因为还没有为菜单创建事件程序,因此,这里只有单击窗口右上角的关闭按钮来关闭窗口了。
接下来就为菜单创建事件程序。将Findfatl.py另存为Findfat2.py,然后进行修改,将每个子菜单项都添加上command设置,修改后的代码如下:
#coding:utf-8
类似的,还需对“清理”和“搜索”这两个下拉菜单中的菜单项编写相应的响应函数。由于还没有编写实现其功能的程序,这里就暂时编写一个替代程序(例如,当选择该菜单命令时,就显示一个对话框),到后面完成相应的功能程序时,再替换就行了。
注意: 一般来说,这种“暂时替代程序”可以让主程序暂时能够正常运行,以方便调试代码。
经过以上修改,程序又能正常运行了。运行后将显示一个窗口,选择菜单“系统”→“关于”命令,将弹出一个信息提示窗口,如图20.3所示。当然,选择其他菜单命令也会弹出相应的信息提示窗口。现在,选择“系统”→“退出”命令,就可关闭窗口了。
20.3 清理垃圾文件
GUI界面制作完成之后,接下来就该编写程序来实现相应的功能了。首先来实现清理垃圾文件的功能,在“清理”下拉菜单中有两个子菜单项“扫描垃圾文件”和“删除垃圾文件”。要完成这两项功能,都需要找到垃圾文件所在位置,由于计算机中垃圾文件的分布是随机的,在各子目录中都有可能有垃圾文件,因此,首先就需要编写程序对目录进行遍历。
20.3.1 迭代目录
要遍历目录,有其他程序设计语言经验的读者首先就可以想到,可以使用递归算法来进行遍历。例如,如下程序就可遍历“C:\python32”目录,将该目录及其子目录中的文件名逐个输出。
在上面的程序中,首先使用os模块中的listdir方法获取传入参数(目录)中的所有文件和子目录,然后循环处理。具体的处理过程是:首先输出当前项(文件或目录)的名称(使用join方法将父目录名和当前项连接起来),然后判断当前项为目录,则递归调用traverse函数处理下层子目录。有关递归算法的用法,可参考算法相关的书籍。
当然,在以上程序中将函数traverse的参数换成其他目录,就可以遍历相应目录下的文件了。另外,在上面的遍历程序中,只是输出文件名,也可以这里的输出操作换成其他操作。
在Python中,os模块提供了一个名为walk的函数,这个函数就可以完成递归的功能。该函数将返回一个元组(root,dirs,files),其中的root表示当前目录,dirs是当前目录下的所有子目录,而files则表示当前目录下的所有文件。下面的程序可完成对指定目录的遍历,并输出文件名(与traverse.py程序的功能相同):
20.3.2 扫描垃圾文件
学会编写程序遍历目录后,再回到案例中来,接下来就可编写程序,遍历目录找出所有的垃圾文件,并进行统计。
在这里,先对垃圾文件进行定义。最简单的方法就是通过文件的扩展名进行界定,例如扩展名为tmp、bak、old、wbk、xlk、_mp、log、gid、chk、syd、$$$、、~*等的文件都是垃圾文件(当然这个列表可以扩充)。因此,在遍历目录时就可判断文件扩展名是否为列表中的内容,若是,则该文件就是垃圾文件。
将上节中编写的Findfat2.py另存为Findfat3.py,然后进行修改。
首先在程序开始处编写以下内容,导入os和os.path模块(处理文件需要使用),然后将定义为垃圾文件的扩展名保存到一个全局变量rubbishExt列表中。
#coding:utf-8
对于rubbishExt列表可进行扩展(注意,这里将log定义为垃圾文件,很多日志文件的扩展名为log,如果调试或分析系统时需要用到,则不要将其定义为垃圾文件进行删除)。
接着,在Windows类中编写以下函数,进行垃圾文件扫描。
最后,修改函数MenuScanRubbish,只需要在原有程序下方增加一行调用ScanRubbish函数即可,修改后的MenuScanRubbish函数如下:
20.3.3 多线程加速
出现这个问题的原因是什么呢?在Python程序遍历目录时需要用很长的时间,可能是几分钟,也可能是几十分钟甚至几个小时。在执行遍历程序时,窗口就无法响应其他操作。因此,就出现了前面的这些问题。
该怎么办?这时就应该使用Python的多线程操作了,将耗时的操作用另一个后台线程去进行,则前台GUI界面仍然可响应用户操作。
在使用多线程,需要导入threading模块,继续修改Findfat.py程序,在前面添加导入threading模块的程序,修改内容如下:
20.3.4 扫描垃圾文件扫描所有磁盘
到目前为止,已经编写完成了扫描垃圾文件的程序。但是,还有一问题,前面的扫描程序都扫描C盘,没有对其他硬盘进行扫描。
接下来编写程序,对所有磁盘进行扫描。将Findfat3.py程序另存为Findfat4.py,然后开始新功能的扩展。
在Python的os和os.path模块中没有提供获取当前计算机盘符的方法(盘符只是DOS或Windows中才有的概念),不过,也可以通过编写Python程序来获取当前计算机中有哪些盘符。以下程序就是一种方法。
在以上函数中,循环处理整数65~90,将这些整数通过Chr方法转换为字母A~Z,分别表示Windows中的A盘~Z盘,通过os.path.isdir方法判断“C:/”~“Z:/”是不是一个有效的目录,如果是,则表示存在这个盘符。函数最后返回一个元组。
获取所有盘符后,接下来还需要修改ScanRubbish函数,将该函数修改为可接受一个元组参数scanpath(元组参数中保存中盘符或一系列目录),然后在循环扫描代码部分添加一个外层循环,循环处理参数scanpath中的每一个元素,具体程序修改为如下形式:
最后,还需要修改MenuScanRubbish函数,在该函数中调用GetDrives函数获取所有盘符,再将这些盘符作为参数传递给
ScanRubbish函数(在初始化线程时传入),程序修改为如下形式:
运行Findfat4.py,选择菜单“清理”→“扫描垃圾文件”命令,Python将对当前计算机中所有磁盘进行扫描,最后得到如图20.6所示的结果。
注意: 当计算机中有多个磁盘,且保存的文件较多时,这个扫描过程将需较长时间。
20.3.5 删除垃圾文件
下面编写删除垃圾文件的程序,将Findfat4.py另存为Findfat5.py,开始编写新的程序。删除垃圾文件的程序与扫描垃圾文件的程序相似,只是在找到垃圾文件后增加一条删除文件的程序代码即可。需要注意的是,在Windows中有些临时文件是系统当前正在使用的,无法删除。因此需要增加一个异常处理,当删除出现异常时跳过即可。删除垃圾文件的函数如下:
20.4 搜索文件
其实,编写好扫描垃圾文件的程序后,再编写搜索文件的程序就很简单了。同样是遍历计算机中所有磁盘,然后再匹配指定条件即可。
20.4.1 搜索超大文件
虽然现在计算机中的硬盘容量越来越大,但是随着使用时间延长,总感觉硬盘空间不够用。每隔一段时间,就会为腾出更多磁盘空间进行一番操作。
其实,经常会有很多非常大的文件藏在磁盘的某一个角落,可能这些文件几年都没有使用过。将这些文件找出来,转移到移动硬盘(或直接删除),就可让硬盘空出一定的空间。
如果人工逐个目录去查找,费时费力,还有可能遗漏。这时,当然就该Python出场了。接着上节的案例继续编写搜索大文件的程序,将Findfat5.py程序另存为Findfat6.py,就可以开始编写程序了。在搜索大文件之前,需要用户确定大文件的界限,即多大的文件算大文件。最好的方式就是使用tkinter的标准对话框。在前面的程序中使用了tkinter.messagebox模块中的方法来显示信息,而接收用户输入的标准对话框可使用tkinter.simpledialog模块中的相关方法。因此,首先需导入该查模块。如下所示程序导入tkinter.simpledialog模块。
接下来修改MenuScanBigFile函数,将该函数原有程序全部删除,改写为以下内容:
在上面的程序中,首先调用tkinter.simpledialog.askinteger方法,接收用户输入一个文件大小的整数值,接着创建一个线程,在线程构造函数中调用ScanBigFile函数搜索大文件,并将用户输入的文件大小s作为元给传入。
最后编写ScanBigFile函数,具体内容如下:
在上面的程序中,遍历计算机中所有磁盘的每一个目录,通过os.path.getsize方法获取文件的大小,然后和传入的参数filesize进行比较,若比filesize大,则找到一个大文件,将其添加到列表框中。
运行Findfat6.py程序,选择菜单“搜索”→“搜索大文件”命令,将显示如图20.8左图所示的对话框,输入文件大小,单击“OK”按钮开始搜索大文件,最后的结果如图20.8右图所示。
20.4.2 按名称搜索文件
与搜索大文件类似,要搜索文件名中包含部分字符的文件,也需要用户输入要搜索文件名的部分字符,然后遍历磁盘各目录,逐个比对文件名。
首先修改MenuSearchFile函数的程序,将原来该函数中的内容全部删除,改为以下内容:
以上程序中首先让用户输入文件名中的部分字符,然后创建一个线程,调用SearchFile函数,传入用户输入的字符串进行搜索。接着编写SearchFile函数的代码如下:
在以上程序中,使用upper函数将传入的文件名部分字符转换为大写,接着遍历计算机磁盘的目录,用find方法逐个比较文件名字符,如果有相同的内容(即find函数返回值大于等于0,若find函数返回值为-1,则表示没有相同字符串)表示找到一个文件,将其添加到文本框中即可。
运行Findfat7.py程序,选择菜单“搜索”→“按名称搜索文件”命令,将弹出一个对话框,在其中输入要搜索文件名的部分字符,如图20.9左图所示。单击“OK”按钮,Python就开始搜索计算机中是否存在文件名中包含“Findfat”的文件,经过一段时间的搜索,最后得到如图20.9右图所示的结果。
20.5 小结
本章介绍了用Python编写Windows优化程序的案例,案例中综合运用了GUI设计、多线程、文件目录访问等多个知识点。这个案例主要完成了3部分功能:首先演示了使用tkinter模块创建GUI界面的全过程;接着介绍了遍历目录程序的编写方法,在此基础上,通过遍历目录,对计算机中的垃圾文件进行扫描、删除操作;最后还通过遍历完成文件的搜索功能。在本案例中,为了使图形界面能随时响应用户操作,对遍历目录这种耗时操作使用了多线程技术进行处理。