假定正在做一个项目,它的文件保存在C:\AlsPythonBook
文件夹中。
并希望为整个文件夹创建一个ZIP文件,作为“快照”。
希望保存不同的版本以及ZIP文件的文件名每次创建时都有所变化。
例如 AlsPythonBook_1.zip
、AlsPythonBook_2.zip
、
AlsPythonBook_3.zip
,等等。这些可以手工完成,
而且可能不小心弄错 ZIP 文件的编号。
运行一个程序来完成这个烦人的任务会简单得多。
针对这个项目,打开一个新的文件编辑器窗口,
将它保存为 backupToZip.py
。
弄清楚 ZIP 文件的名称
这个程序的代码将放在一个名为 backupToZip()
的函数中。
这样就更容易将该函数复制粘贴到其他需要这个功能的Python程序中。
在这个程序的末尾,会调用这个函数进行备份。让程序看起来像这样:
backupToZip.py
- 将一个完整文件夹及其内容复制到文件名自动递增的ZIP压缩文件中。
#! python3
import zipfile, os
def backupToZip(folder):
# Backup the entire contents of "folder" into a ZIP file.
folder = os.path.abspath(folder) # make sure folder is absolute
# Figure out the filename this code should use based on
# what files already exist.
number = 1
while True:
zipFilename = os.path.basename(folder) + '_' + str(number) + '.zip'
if not os.path.exists(zipFilename):
break
number = number + 1
# TODO: Create the ZIP file.
# TODO: Walk the entire folder tree and compress the files in each folder.
print('Done.')
backupToZip('F:\\delicious')
Done.
先完成基本任务:添加 #!
行,描述该程序做什么,
并导入 zipfile
和 os
模块。
定义 backupToZip()
函数,它只接收一个参数,
即 folder
。这个参数是一个字符串路径,
指向需要备份的文件夹。该函数将决定它创建的ZIP文件使用什么文件名,
然后创建该文件,
遍历 folder 文件夹,将每个子文件夹和文件添加到ZIP文件中。
在源代码中为这些步骤写下 TODO
注释,提醒稍后来完成。
第一部分命名这个ZIP文件,使用folder 的绝对路径的基本名称。
如果要备份的文件夹是 C:\delicious , ZIP 文件的名称就应该是 delicious_N.zip
,
第一次运行该程序时 N = l,第二次运行时 N =2,以此类推。
通过检查 delicious_1.zip
是否存在,
然后检查 delicious_2.zip
是否存在,继续下去,
可以确定 N 应该是什么。用一个名为 number
的变量表示 N,
在一个循环内不断增加它,并调用 os.path.exists()
来检查该文件是否存在。
第一个不存在的文件名将导致循环 break
,
因此它就发现了新 ZIP 文件的文件名。
创建新 ZIP 文件
接下来创建 ZIP 文件。让程序看起来像这样:
#! python3
# backupToZip.py - Copies an entire folder and its contents into
# a ZIP file whose filename increments.
--snip--
while True:
zipFilename = os.path.basename(folder) + '_' + str(number) + '.zip'
if not os.path.exists(zipFilename):
break
number = number + 1
# Create the ZIP file.
print('Creating %s...' % (zipFilename))
backupZip = zipfile.ZipFile(zipFilename, 'w')
# TODO: Walk the entire folder tree and compress the files in each folder.
print('Done.')
backupToZip('F:\\delicious')
backupToZip.py
- 将整个文件夹及其内容备份至文件名自动递增的zip压缩包。
#! python3
import zipfile, os
folder = os.path.abspath('.') # make sure folder is absolute
注意, 不要将备份的结果文件放到要备份的文件夹中,不然备份程序会循环读取备份的结果文件,导致结果文件无限变大,直至充满硬盘空间。
这里为了方便将文件保存到 /tmp
文件夹中。实际使用要放到恰当的位置。
检查当前目录/指定路径下已经存在的文件。
number = 1
while True:
zipFilename = '/tmp/xx_' + os.path.basename(folder) + '_' + str(number) + '.zip'
if not os.path.exists(zipFilename):
break
number = number + 1
创建ZIP压缩文件。
print('Creating %s...' % (zipFilename))
backupZip = zipfile.ZipFile(zipFilename, 'w')
Creating /tmp/xx_ch01_文件管理_1.zip...
遍历整个文件夹树并压缩每个文件夹中的文件。
for foldername, subfolders, filenames in os.walk(folder):
print('Adding files in %s...' % (foldername))
# Add the current folder to the ZIP file.
backupZip.write(foldername)
# Add all the files in this folder to the ZIP file.
for filename in filenames:
if filename.startswith(os.path.basename(folder) + '_') and filename.endswith('.zip'):
continue # don't backup the backup ZIP files
backupZip.write(os.path.join(foldername, filename))
backupZip.close()
print('Done.')
Adding files in /home/jovyan/work/jupylab_houxue/pt04_essential/ch01_文件管理... Adding files in /home/jovyan/work/jupylab_houxue/pt04_essential/ch01_文件管理/.ipynb_checkpoints... Adding files in /home/jovyan/work/jupylab_houxue/pt04_essential/ch01_文件管理/archive... Adding files in /home/jovyan/work/jupylab_houxue/pt04_essential/ch01_文件管理/archive/.ipynb_checkpoints... Done.
可以在 for
循环中使用 os.walk
,在每次迭代中,
它将返回这次迭代当前的文件夹名称、这个文件夹中的子文件夹,
以及这个文件夹中的文件名。
在这个 for
循环中,该文件夹被添加到 ZIP 文件。
嵌套的 for
循环将遍历
filenames
列表中的每个文件。
每个文件都被添加到 ZIP 文件中,以前生成的备份
ZIP 文件除外。
如果运行该程序,它产生的输出看起来像这样:
Creating delicious_1.zip...
Adding files in C:\delicious...
Adding files in C:\delicious\cats...
Adding files in C:\delicious\waffles...
Adding files in C:\delicious\walnut...
Adding files in C:\delicious\walnut\waffles...
Done.
小结
即使是一个有经验的计算机用户, 可能也会用鼠标和键盘手工处理文件。 现在的文件浏览器使得处理少量文件的工作很容易。 但有时候,如果用计算机的浏览器, 需要完成的任务可能要花几个小时。
os
和 shutil
模块提供了一些函数,
用于复制、移动、改名和删除文件。在删除文件时,
可能希望使用 send2trash
模块,
将文件移动到回收站或垃圾箱,
而不是永久地删除它们。在编程处理文件时,
最好是先注释掉实际会复制/移动/改名/删除文件的代码,
添加 print()
调用,
这样就可以运行该程序,验证它实际会做什么。
通常,不仅需要对一个文件夹中的文件执行这些操作,
而是对所有下级子文件夹执行操作。os.walk()
函数将处理这个艰苦工作,
遍历文件夹,这样就可以专注于程序需要对其中的文件做什么。
zipfile
模块提供了一种方法,用Python压缩和解压ZIP归档文件。
和 os
和 shutil
模块中的文件处理函数一起使用,
很容易将硬盘上任意位置的一些文件打包。
和许多独立的文件相比,这些 ZIP 文件更容易上传到网站,
或作为 E-mail 附件发送。
本书前面几章提供了源代码供拷贝。 但如果编写自己的程序,可能在第一次编写时不会完美无缺。 下一章将聚焦于一些Python模块,它们帮助分析和调试程序, 这样就能让程序很快正确运行。