第十章 解决问题--编写一个python脚本

来源:互联网 发布:玛丽苏 知乎 编辑:程序博客网 时间:2024/06/05 15:49
部分转自http://www.cnblogs.com/iswszheng/archive/2009/08/18/1548945.html
第十章 解决问题--编写一个python脚本

问题: 

想要一个可以为所有重要文件创建备份的程序。
我们如何确定该备份哪些文件?备份保存在哪里?我们怎么样存储备份?
1. 需要备份的文件和目录由一个列表指定。
2. 备份应该保存在主备份目录中。
3. 文件备份成一个zip文件。
4. zip存档的名称是当前的日期和时间。
5. 我们使用标准的zip命令,它通常默认地随Linux/Unix发行版提供。Windows用户可以使用Info-Zip程序。注意你可以使用任何的存档命令,只要它有命令行界面就可以了,那样的话我们可以从我们的脚本中传递参数给它。
_____________________________________________________

解决方案

我们经常会与文件和目录打交道,对于这些操作python提供了一个os模块,里面包含了很多操作文件和目录的函数。
time.strftime()可以用来获得当前时间,可以将时间格式化为字符串等等
________________________________________________________________

版本一

linux版本

import osimport timesource = ['/home/swaroop/byte', '/home/swaroop/bin']#要备份的文件的目录 # If you are using Windows, use source = [r'C:\Documents', r'D:\Work'] or something like thattarget_dir = '/mnt/e/backup/' #目标目录target = target_dir + time.strftime('%Y%m%d%H%M%S') + '.zip'# 5. We use the zip command (in Unix/Linux) to put the files in a zip archivezip_command = "zip -qr '%s' %s" % (target, ' '.join(source))if os.system(zip_command) == 0:    print 'Successful backup to', targetelse:    print 'Backup FAILED'
输出:
Successful backup to /mnt/e/backup/20041208073244.zip
我们创建了zip_command字符串,它包含我们将要执行的命令。
zip命令有一些选项和参数。-q选项用来表示安静模式,在压缩的时候不显示指令的执行过程。-r选项表示zip命令对目录递归地工作,即它包括子目录以及子目录中的文件。两个选项可以组合成缩写形式-qr。选项后面跟着待创建的zip归档的名称,然后再是待备份的文件和目录列表。我们使用已经学习过的字符串join方法把source列表转换为字符串。
最后,我们使用os.system函数运行命令,利用这个函数就好像在 系统 中运行命令一样。即在shell中运行命令——如果命令成功运行,它返回0,否则它返回错误号。os.system("命令")
---------------------------------------
是Windows把反斜杠(\)作为目录分隔符,而Python用反斜杠表示转义符!
所以,你得使用转义符来表示反斜杠本身或者使用自然字符串。例如,使用'C:\\Documents'或r'C:\Documents'而不是'C:\Documents'
---------------------------------------

用windows版本

import os  import time  source =[r'd:\doc', r'd:\doc1'] target_dir = 'd:\\work\\' #这里不能用r'd:\work\',因为自然字符串不能以\结尾。target = target_dir + time.strftime('%Y%m%d%H%M%S') + '.zip'  zip_command = "zip -qr \"%s\" \"%s\"" % (target, '" "'.join(source))if os.system(zip_command) == 0:      print 'Successful backup to', target  else:      print 'Backup FAILED'
输出:
Successful backup to d:\work\20130817013518.zip
这里:
>>> zip_command = "zip -qr \"%s\" \"%s\"" % (target, '""'.join(source))#情况1>>> zip_command'zip -qr "d:\\work\\20130817012412.zip" "d:\\doc""d:\\doc"'>>> zip_command = "zip -qr \"%s\" \"%s\"" % (target, '" "'.join(source))#情况2>>> zip_command'zip -qr "d:\\work\\20130817012412.zip" "d:\\doc" "d:\\doc"'>>> zip_command = "zip -qr \"%s\" \"%s\"" % (target, '\" \"'.join(source))#情况3>>> zip_command'zip -qr "d:\\work\\20130817012412.zip" "d:\\doc" "d:\\doc"'>>> zip_command = "zip -qr \"%s\" \"%s\"" % (target, ' '.join(source))#情况4>>> zip_command'zip -qr "d:\\work\\20130817013518.zip" "d:\\doc d:\\doc"'>>> 
情况2和情况3是对的。
情况1错在,参数地址间要有空格。
情况4错在,windows命令行带空格的话,路径参数要用双引号引起来。

source =r'd:\doc' target_dir = 'd:\\work\\' target = target_dir + time.strftime('%Y%m%d%H%M%S') + '.zip'  zip_command = "zip -qr \"%s\" \"%s\"" % (target, source)"""这里zip_command = "zip -qr "%s" "%s"" % (target, source)不行,因为双引号里嵌套双引号里面字符串就无效了哦,双引号是两两配对的.zip_command = "zip -qr '%s' '%s'" % (target, source)也不行,因为windows中命令行带空格的话,路径参数要用双引号引起来,不能用单引号。"""
_____________________________________________________

版本二——采用更好的文件名机制

使用 时间 作为文件名,而当前的 日期 作为目录名,存放在主备份目录中
import osimport timesource =[r'd:\doc', r'd:\doc1']target_dir = 'd:\\work\\' today = target_dir + time.strftime('%Y%m%d')#目录名now = time.strftime('%H%M%S')#文件名if not os.path.exists(today):#若目录名不存在,这里用os.path.isdir感觉更好    os.mkdir(today) # 创建目录    print 'Successfully created directory', todaytarget = today + os.sep + now + '.zip'zip_command = "zip -qr \"%s\" \"%s\"" % (target, '" " '.join(source))if os.system(zip_command) == 0:    print 'Successful backup to', targetelse:    print 'Backup FAILED'
输出:
Successfully created directory d:\work\20130817
Successful backup to d:\work\20130817\142124.zip
-----------------------------------------

os.sep变量的用法

这会根据你的操作系统给出目录分隔符,即在Linux、Unix下它是'/',在Windows下它是'\\',而在Mac OS下它是':'。
使用os.sep而非直接使用字符,会使我们的程序具有移植性,可以在上述这些系统下工作。
----------------------------------------

os目录操作

os.mkdir()函数创建目录:os.mkdir(path)
>>> import os
>>> os.mkdir('E:\\book\\temp')

os.rmdir()函数删除目录,用法与mkdir相同
使用os.path.isdir()函数判断某一路径是否为目录,用法与前两个相同。若是目录,则返回True.
使用os.path.exists()函数判断某一路径是否存在。用法与前面相同。
-----

os.path.exists 和 os.path.isdir的区别

这两个的区别我百度了一下,有人给出以下解释。
os.path.exists will also return True if there's a regular file with that name.
os.path.isdir will only return True if that path exists and is a directory.
Just like it sounds like: if the path exists, but is a file and not a directory, isdir will return False. Meanwhile, exists will return True in both cases.
如果是一个普通的文件的名字,而不是目录,os.path.exists也将返回true,只要物理路径存在。
只有存在该路径且是一个目录,os.path.isdir才返回True。
例子:
这里d:\work1是一个无扩展名的文件,不是目录。
>>> os.path.isdir('d:\\work')True>>> os.path.isdir('d:\\work1')False>>> os.path.exists('d:\\work')True>>> os.path.exists('d:\\work1')True>>> 
_____________________________________________________

版本三——在zip归档名上附带一个用户提供的注释

import osimport timesource =[r'd:\doc', r'd:\doc1']target_dir = 'd:\\work\\'today = target_dir + time.strftime('%Y%m%d')now = time.strftime('%H%M%S')# Take a comment from the user to create the name of the zip filecomment = raw_input('Enter a comment --> ')#此处输入时必须带双引号,比如输入"OK",前面说过,windows命令行目录中空格隔开目录时必须是用双引号隔开if len(comment) == 0: # check if a comment was entered    target = today + os.sep + now + '.zip'else:    target = today + os.sep + now + '_' +comment.replace(' ', '_') + '.zip'#replace方法,用后面字符串代替前面字符串,避免目录中出现空格if not os.path.exists(today):    os.mkdir(today)     print 'Successfully created directory', todayzip_command = "zip -qr \"%s\" \"%s\"" % (target, '" " '.join(source))if os.system(zip_command) == 0:    print 'Successful backup to', targetelse:    print 'Backup FAILED'
输出:
>>> 
Enter a comment --> "OK"
Successfully created directory d:\work\20130817
Successful backup to d:\work\20130817\150040_"OK".zip
>>>
------------------------------------
这里若一个逻辑行改为了两个物理行,则出错
else:    target = today + os.sep + now + '_' +        comment.replace(' ', '_') + '.zip'
应改为:
else:    target = today + os.sep + now + '_' +\        comment.replace(' ', '_') + '.zip'
————————————————————————————————————————

进一步优化

可以在程序中包含 交互 程度——你可以用-v选项来使你的程序更具交互性。
另一个可能的改进是使文件和目录能够通过命令行直接传递给脚本。我们可以通过sys.argv列表来获取它们,然后我们可以使用list类提供的extend方法把它们加到source列表中去。
我还希望有的一个优化是使用tar命令替代zip命令。这样做的一个优势是在你结合使用tar和gzip命令的时候,备份会更快更小。
如果你想要在Windows中使用这些归档,WinZip也能方便地处理这些.tar.gz文件。tar命令在大多数Linux/Unix系统中都是默认可用的。Windows用户也可以下载安装它。

命令字符串现在将称为:tar = 'tar -cvzf %s %s -X /home/swaroop/excludes.txt' % (target, ' '.join(srcdir))
选项解释如下:
● -c表示创建一个归档。
● -v表示交互,即命令更具交互性。
● -z表示使用gzip滤波器。
● -f表示强迫创建归档,即如果已经有一个同名文件,它会被替换。
● -X表示含在指定文件名列表中的文件会被排除在备份之外。例如,你可以在文件中指定*~,从而不让备份包括所有以~结尾的文件。
重要
最理想的创建这些归档的方法是分别使用zipfile和tarfile。它们是Python标准库的一部分。使用这些库就避免了使用os.system这个不推荐使用的函数,它容易引发严重的错误。
———————————————————————————————

软件开发过程

1. 什么(分析)
2. 如何(设计)
3. 编写(实施)
4. 测试(测试与调试)
5. 使用(实施或开发)
6. 维护(优化)
原创粉丝点击