Python Cookbook-2.29 带版本号的文件名
任务
如果你想在改写某文件之前对其做个备份,可以在老文件的名字后面根据惯例加上三个数字的版本号。
解决方案
我们需要编写一个函数来完成备份工作:
def VersionFile(file_spec, vtype='copy'):
import os,shutil
if os.path.isfile(file_spec):
#检查'vtype'参数
if vtype not in('copy','rename'):
raise ValueError,'Unknown vtype %r' % (vtype,)
#确定根文件名,所以扩展名不会太长
n,e = os.path.splitext(file_spec)
#是不是一个以点为前导的三个数字?
if len(e) == 4 and e[1:].isdigit():
num = 1+int(e[1:])
root = n
else:
num = 0
root = file_spec
#寻找下一个可用的文件版本
for i in xrange(num,1000):
new_file = '%s.%03d' %(root,i)
if not os.path.exists(new_file):
if vtype =='copy':
shutil.copy(file_spec,new_file)
else:
os.rename(file_spec,new_file)
return True
raise RuntimeError,"Can't$s%r,all names taken"%(vtype,file_spec)
return False
if __name__ == '__main__':
import os
#创建一个test.txt文件
tfn = 'test.txt'
open(tfn,"w').close()
#对它取3次版本
print VersionFile(tfn)
#输出:True
print VersionFile(tfn)
# 输出:True
print VersionFile(tfn)
#输出:True
#删除我们刚刚生成的test.txt*文件
for x in(''.'.000','.001','.002'):
os.unlink(tfn + x)
#展示当文件不存在时取版本操作的结果
print VersionFile(tfn)
#输出:False
print VersionFile(tfn)
#输出:False
讨论
VersionFile 函数是为了确保在打开文件进行写入或更新等修改前,对已存在的目标文件完成了备份(或者重命名,由可选的第二个参数来决定)。在处理文件之前进行备份是很明智的举措(这也是一些人仍然怀念旧的 VMS操作系统的原因,这种备份是自动进行的)。实际的复制和重命名是分别由shutil.copy和 os.rename 完成的,所以唯一的问题是,怎么确定文件的名字。
一个流行的决定备份的名字的方法是使之版本化(比如,给文件名增加一个逐渐增大的数字)。本节确定文件名的方法是,首先从文件名中分解出名字根(因为有可能这已经是一个版本化的文件名了),然后在这个名字根之后添加进一步的扩展名,比如.000,.001,等等,直到以此种命名方式确定的文件名也无法对应任何一个存在的文件。注意,VersionFile 被限制为只能有1000个版本,所以需要有个归档备份的计划。在进行版本化之前,首先要确保该文件存在–不能对不存在的东西进行备份。如果文件不存在,VersionFile 函数只是简单地返回 False(如果文件存在而且函数执行无误则返回 True),所以在调用之前也无须检査文件是否存在。