还你系统空间的 Python 小程序

Windows 系统用久了,磁盘中就会产生大量的“垃圾”文件。这些文件有的是程序使用过的临时文件,有的是操作记录和日志信息等。因为往往不能被有效地清理干净,越积越多,导致用户的可用空间越来越小。同时也会因为碎片文件过多,使得系统的运行速度受到一定影响。

像我这种强迫症用户显然受不了这种状况,定期清理垃圾文件很有必要。

对于 Windows 系统,网上有一些现成的垃圾文件清理脚本。不过作为一个 Python 学习者,当然要自己动手来实现一个才合理嘛。

Python 的 os 模块,提供了较为丰富的处理系统文件与路径的函数。下面我们就靠它,来实现一个自己的磁盘清理小程序。

动手前的友情提示:

  • 本文附带代码运行环境为 WIN7 + Python 2.7。
  • 某些缓存文件可以提高程序的执行速度,比如缓存 cookie、使用记录 recent、预读取 prefetch 等。所以清理临时文件并不代表系统运行就会变快,有时也可能变慢。
  • 由于牵涉到文件删除操作,请在动手前务必反复确认代码,万一导致什么重要文件被删,本人可概不负责啊。别问我为什么要这么说,写了好几天的代码在调试时被误删了,我再去哭一会儿……(;´༎ຶД༎ຶ`)

言归正传,电脑中的垃圾文件及文件夹主要有下面几类:

系统盘 %system% 下文件类型: 【临时文件(*.tmp)】 【临时文件(*._mp)】 【日志文件(*.log)】 【临时帮助文件(*.gid)】 【磁盘检查文件(*.chk)】 【临时备份文件(*.old)】 【Excel备份文件(*.xlk)】 【临时备份文件(*.bak)】 -------------------------------- 用户目录 %userprofile% 下文件夹 【COOKIE】 cookies\*.* 【文件使用记录】 recent\*.* 【IE临时文件】 Temporary Internet Files\*.* 【临时文件文件夹】 Temp\*.* -------------------------------- Windows 目录 %windir% 下文件夹 【预读取数据文件夹】 prefetch\*.* 【临时文件】 temp\*.*

如果你了解自己使用的软件产生的其它垃圾文件,也可以添加至待删除的列表上。

与我们直接在 Windows 可视化窗口删除文件或文件夹类似,使用 Python 清理磁盘大致亦可分为 获取文件地址判断垃圾文件删除垃圾文件和文件夹 三步:

1. 获取文件地址

在可视化窗口中,我们点击每个文件夹的图标,打开不同文件夹,可以看见窗口的地址栏也随之切换到了对应的目录下,在 Python os 模块中,同样是根据文件地址来查找文件,相应的函数如下:

获取当前目录路径

>>> import os

>>> os.getcwd()

'E:\\Software\\Python27'

跳转至指定的文件目录

>>> os.chdir('d://temporary')

>>> os.getcwd()

'd:\\temporary'

获取系统盘符

>>> os.environ['systemdrive']

'C:'

获取用户目录

>>> os.environ['userprofile']

'C:\\Users\\Administrator'

获取 Windows 目录

>>> os.environ['windir']

'C:\\Windows'

调用 os.environ 函数得到字典格式的系统环境映射表,通过关键字可以很方便地得到我们想要的地址。

使用 os.walk 函数,可生成并展开以指定目录为根目录的目录树。

参数 topdown 指定展开方式是否从顶层到底层

all_info = os.walk('d:\\temporary\\', topdown=False)

os.walk() 函数一般配合如下的 for 循环使用,遍历目录树中每一层的根目录 roots,子目录 dirs 以及文件 files,并将值储存在对应的变量中:

for roots, dirs, files in all_info:

...

例如,对于 D 盘下根目录 AAA 目录树展开如下:

用 walk 函数遍历并输出后,结果如下:

将两个给定的目录进行组合

>>> os.path.join('d:\\', 'temporary')

'd:\\temporary'

用 join 函数,配合 walk 函数得到的根目录与文件名,就能组合出我们想要的文件地址了。

2. 判断垃圾文件

我们现在已知垃圾文件的扩展名(以及垃圾文件夹名),通过 walk 函数与 join 函数也得到了完整的文件名,要判断文件是不是垃圾文件,可以用正则表达式进行匹配判断,正则表达式还不牢固的同学请移步 【Python 第55课】 正则表达式(1)

如果对正则表达式的语法深感头疼,os 模块也有提供其它解决方案:

>>> os.path.splitext(r'aaa\bbb\ccc.ddd')

('aaa\\bbb\\ccc', '.ddd')

os.path.splitext 函数可以将文件的文件名与扩展名进行分离,并返回一个包含文件名与扩展名的二元元组。

得到了文件的扩展名,我们可以用 ‘in’ 来 判断该扩展名是否在需要删除的扩展名列表中:

extension = os.path.splitext(r'aaa\bbb\ccc.ddd')

extension_to_del = ['.aaa', '.bbb', '.ccc', '.ddd']

if extension[1] in extension_to_del:

# to be deleted

这里可能会踩到的一个坑是字符“\”,它既是 Windows 路径的分隔符,又是 Python 字符串中的转义符。在处理路径时,需要额外注意。

3. 删除文件

使用 os 模块删除数据有三点需要注意:

其一,删除文件与删除文件夹调用的是不同的函数。

删除文件

os.remove('d:temporary/test/test.txt')

删除文件夹

os.rmdir('d:temporary/test/empty')

如果你在尝试调用这个代码删除文件/文件夹时无效,确认下文件名是否带有中文、空格和特殊符号。建议先在纯英文的简单路径下调试成功再说。

无法删除的还有一个常见原因是另一个要注意的地方:

其二,os.rmdir 只能删除空文件夹,如果文件夹非空,则会报错。

所以,如果要把匹配到的垃圾文件夹整个删除,可能我们不得不选择先把文件夹中的所有文件全部删除,再从最内层文件夹开始往外逐层删除。这实在是挺麻烦的,那有没有其它解决方案呢?

有,但要依靠 os 以外的帮助。

import shutil

shutil.rmtree('d:/temporary/test/aaa')

上面的解决办法是引用另外一个模块 shutil 的函数来删除非空文件夹,其实,这个外部引用的函数还是用 os 模块的函数来写的,想挑战的话,也可以自己写一个试试。

当然,直接调用 cmd 命令也是极好的:

os.system('rd/s/q "d:temporary/test"')

注意,整个命令是一个字符串,其中目录地址要额外加引号。

在某些情况下,尤其是当前有较多其它程序在运行时,即使用 shutil.rmtree 函数仍然会报错,甚至连删除文件都会报错,这就是第三个注意事项了:

其三,文件正在运行或者受到保护、当前账户没有足够权限时,删除会报错。

这个情况下,对应的文件最后就不要强行删了,不然轻则即使删除了,也会再次自动生成、重则还可能导致正在运行的程序崩溃。

因此,我们在删除文件或文件夹时,加上一个 try except 逻辑结构,跳过那些无法删除的文件:

try:

os.remove(r'd:\temporary\using.xxx')

except WindowsError:

print 'nothing has being removed'

按照上面三个步骤写下来,磁盘清理脚本基本功能已经完善。不过除此之外,我们还可以添加一些数据监控代码,多一些对用户友好的人机交互,比如:

显示文件夹(路径)大小,单位 bite

>>> os.path.getsize('d://temporary/test')

4096

显示文件大小

>>> os.path.getsize('d://temporary/test/aaa.txt')

135

其它功能诸如 定时清理、开关机清理、清理时间统计 等等,都可以尝试实现。欢迎在留言区和论坛上讨论。

原文发布于微信公众号 - Crossin的编程教室(crossincode)

原文发表时间:2017-01-07

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏企鹅号快讯

Node篇 3.NodeJS整合MySQL

我们在上一篇《[JavaScript从入门到放弃] Node篇 2.Express路由分离及传参》简单的学习了设置路由以及获取参数的几种方式,但显然我们只能利用...

37790
来自专栏编程

史上最全Django知识总结!神级程序员强推:掌握此文就掌握Django

一、视图函数(views.py中的函数):第一个参数类型是HttpRequest对象,返回值是HttpResponse对象 二、URLconf(urls.py)...

67570
来自专栏数据库

详解Redis内部运作机制

纯手工打造每一篇开源资讯与技术干货,数十万程序员和Linuxer已经关注。 Linux技术交流QQ群:2659793(十二月最新!!) Redis数据库(Red...

22470
来自专栏玄魂工作室

看代码学渗透 Day5 - escapeshellarg与escapeshellcmd使用不当

--------------------------------------------------------------------------------...

35720
来自专栏农夫安全

代码审计入门总结

0x00 简介 ---- 之前看了seay写的PHP代码审计的书,全部浏览了一遍,作为一个代码审计小白,希望向一些和我一样的小白的人提供一下我的收获,以及一个整...

36970
来自专栏13blog.site

Spring+SpringMVC+MyBatis+easyUI整合基础篇(八)mysql中文查询bug修复

前言   在测试搜索时出现的问题,mysql通过中文查询条件搜索不出数据,但是英文和数字可以搜索到记录,中文无返回记录。本文就是写一下发现问题的过程及解决方法...

34550
来自专栏大内老A

WCF技术剖析之二十三:服务实例(Service Instance)生命周期如何控制[上篇]

服务调用的目的体现在对某项服务功能的消费上,而功能的实现又定义在相应的服务类型中。不论WCF服务端框架处理服务调用请求的流程有多么复杂,最终都落实在服务实例的激...

25080
来自专栏北京马哥教育

Python imports指南

来源:Python程序员 ID:pythonbuluo 声明:如果你每天写Python,你会发现这篇文章中没有新东西。 这是专为那些像运维人员等偶尔使用Pyt...

26150
来自专栏JavaEdge

Java线程状态

实现Runnable接口和继承Thread可以得到一个线程类,new一个实例出来,线程就进入了初始状态 英文翻译过来是线程还是没有开始执行。 首先,既然已经...

548110
来自专栏水击三千

UML学习-时序图

时序图(Sequence Diagram)是显示对象之间交互的图,这些对象是按时间顺序排列的。顺序图中显示的是参与交互的对象及其对象之间消息交互的顺序。时序图...

41190

扫码关注云+社区

领取腾讯云代金券