导航
导航
文章目录
  1. 10.1 问题
  2. 10.2 解决方案
    1. 版本一
    2. 输出
    3. 如何工作
    4. 版本二
    5. 输出
    6. 如何工作
    7. 版本三
    8. 输出
    9. 如何不工作
    10. 版本四
    11. 输出
    12. 如何工作
    13. 进一步优化

简明Python教程-10.解决问题——编写一个Python脚本

10.1 问题

为所有重要文件备份
分析:如何确定该备份哪些文件?备份保存在哪里?怎么样存储备份?
设计:
1、需要备份一的文件和目录由一个列表制定
2、备份保存在主备份目录中
3、备份成一个zip文件
4、zip存档的名称是当前的日期和时间
5、使用标准的zip命令(Linux/Unix默认,Windows可使用Info-Zip等,只要有命令行界面可以在脚本中给它传递参数即可)

10.2 解决方案

实施:

版本一

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#!/usr/bin/python
# Filename: backup_ver1.py

import os
import time

# 1. The files and directories to be backed up are specified in a list.
source = ['/home/swaroop/byte', '/home/swaroop/bin']
# If you are using Windows, use source = [r'C:\Documents', r'D:\Work'] or something like that

# 2. The backup must be stored in a main backup directory
target_dir = '/mnt/e/backup/' # Remember to change this to what you will be using

# 3. The files are backed up into a zip file.
# 4. The name of the zip archive is the current date and time
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 archive
zip_command = "zip -qr '%s' %s" % (target, ' '.join(source))

# Run the backup
if os.system(zip_command) == 0:
print 'Successful backup to', target
else:
print 'Backup FAILED'

输出

1
2
$ python backup_ver1.py
Successful backup to /mnt/e/backup/20041208073244.zip

现在已经处于测试环节了,测试程序是否正确工作
如果结果与期望不一样,就得调试程序,即消除程序中的错误

如何工作

设计 一步一步地转换为 代码
1、要使用了os和time模块,现在程序中引入它们
2、source列表指定需要备份的文件和目录;target_dir变量制定存储备份文件的目标目录;zip归档的名称是目前的日期和时间,由time.strftime()函数获得,并加上.zip扩展名
2.a time.strftime()函数需要使用定制,%Y会被无世纪的年份替代,%m会被01到12之间的月份替代,以此类推。这些定制的详细情况可以在Python的发行版中的《Python参考手册》中获得,与print语句的定制(%后跟一个元组)类似,但不完全相同
2.b 使用加法操作符来 级连 字符串,即把两个字符串连接在一起,返回一个新的字符串
3、创建zip_command字符串,包含将要执行的命令
3.a 可以在shell(Linux终端或DOS提示符)中运行它,检验它是否工作
3.b zip命令有一些选项和参数,-q选项表示zip命令安静地工作,-r选项表示对目录递归地工作,即包括子目录及子目录中的文件,两个选项可以组合写成-qr,选项后是待创建的zip归档的名称
3.c 使用字符串的join方法,把source列表转换为字符串
4、使用os.system函数运行命令,利用这个函数就好像在 系统 中运行命令一样,成功返回0,否则返回错误号
5、根据打印的消息,显示备份是否创建成功
(注意,Windows把反斜杠()作为目录分隔符,而Python用反斜杠表示转义符,因此在source和target目录中,需要转义’C:\Documents’或者使用自然字符串r’C:\Documents’)
这被称为软件的 开发 环节。上述程序可以正确工作,但如果在使用中发生问题,则应回到设计环节或者调试程序

版本二

版本一可以工作,但我们可以对它进行优化让它在日常工作中变得更好,这称为软件的维护环节
例如文件名机制,可以使用当前日期作为目录名,当前时间作为文件名,存放在主备份目录中。优势是便于管理且文件名更短

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#!/usr/bin/python
# Filename: backup_ver2.py

import os
import time

# 1. The files and directories to be backed up are specified in a list.
source = ['/home/swaroop/byte', '/home/swaroop/bin']
# If you are using Windows, use source = [r'C:\Documents', r'D:\Work'] or something like that

# 2. The backup must be stored in a main backup directory
target_dir = '/mnt/e/backup/' # Remember to change this to what you will be using

# 3. The files are backed up into a zip file.
# 4. The current day is the name of the subdirectory in the main directory
today = target_dir + time.strftime('%Y%m%d')
# The current time is the name of the zip archive
now = time.strftime('%H%M%S')

# Create the subdirectory if it isn't already there
if not os.path.exists(today):
os.mkdir(today) # make directory
print 'Successfully created directory', today

# The name of the zip file
target = today + os.sep + now + '.zip'

# 5. We use the zip command (in Unix/Linux) to put the files in a zip archive
zip_command = "zip -qr '%s' %s" % (target, ' '.join(source))

# Run the backup
if os.system(zip_command) == 0:
print 'Successful backup to', target
else:
print 'Backup FAILED'

输出

1
2
3
4
5
6
$ python backup_ver2.py
Successfully created directory /mnt/e/backup/20041208
Successful backup to /mnt/e/backup/20041208/080020.zip

$ python backup_ver2.py
Successful backup to /mnt/e/backup/20041208/080428.zip

如何工作

与版本一大部分相同,但使用os.exists函数,检验在主备份目录中是否有以当前日期明明的目录,如果没有,使用os.mkdir函数创建
os.sep变量根据操作系统给出目录分隔符(Linux/Unix下是’/‘,Windows下是’\’,Mac OS下是’:’),使用os.sep比直接使用字符更具有移植性

版本三

当备份多的时候无法区分备份内容,可以让用户对备份输入注释,添加到zip归档的文件名上

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#!/usr/bin/python
# Filename: backup_ver3.py

import os
import time

# 1. The files and directories to be backed up are specified in a list.
source = ['/home/swaroop/byte', '/home/swaroop/bin']
# If you are using Windows, use source = [r'C:\Documents', r'D:\Work'] or something like that

# 2. The backup must be stored in a main backup directory
target_dir = '/mnt/e/backup/' # Remember to change this to what you will be using

# 3. The files are backed up into a zip file.
# 4. The current day is the name of the subdirectory in the main directory
today = target_dir + time.strftime('%Y%m%d')
# The current time is the name of the zip archive
now = time.strftime('%H%M%S')

# Take a comment from the user to create the name of the zip file
comment = raw_input('Enter a comment --> ')
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'

# Create the subdirectory if it isn't already there
if not os.path.exists(today):
os.mkdir(today) # make directory
print 'Successfully created directory', today

# 5. We use the zip command (in Unix/Linux) to put the files in a zip archive
zip_command = "zip -qr '%s' %s" % (target, ' '.join(source))

# Run the backup
if os.system(zip_command) == 0:
print 'Successful backup to', target
else:
print 'Backup FAILED'

输出

1
2
3
4
5
$ python backup_ver3.py
File "backup_ver3.py", line 25
target = today + os.sep + now + '_' +
^
SyntaxError: invalid syntax

如何不工作

这个程序不工作,Python提示有一个语法错误,根据给出的错误的位置,从那行开始 调试 程序
观察发现,有一个逻辑行,被分成了两个物理行,但没有指明这两个物理行属于同一逻辑航,需要使用反斜杠来表示逻辑航在下一物理行继续

版本四

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#!/usr/bin/python
# Filename: backup_ver4.py

import os
import time

# 1. The files and directories to be backed up are specified in a list.
source = ['/home/swaroop/byte', '/home/swaroop/bin']
# If you are using Windows, use source = [r'C:\Documents', r'D:\Work'] or something like that

# 2. The backup must be stored in a main backup directory
target_dir = '/mnt/e/backup/' # Remember to change this to what you will be using

# 3. The files are backed up into a zip file.
# 4. The current day is the name of the subdirectory in the main directory
today = target_dir + time.strftime('%Y%m%d')
# The current time is the name of the zip archive
now = time.strftime('%H%M%S')

# Take a comment from the user to create the name of the zip file
comment = raw_input('Enter a comment --> ')
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'
# Notice the backslash!

# Create the subdirectory if it isn't already there
if not os.path.exists(today):
os.mkdir(today) # make directory
print 'Successfully created directory', today

# 5. We use the zip command (in Unix/Linux) to put the files in a zip archive
zip_command = "zip -qr '%s' %s" % (target, ' '.join(source))

# Run the backup
if os.system(zip_command) == 0:
print 'Successful backup to', target
else:
print 'Backup FAILED'

输出

1
2
3
4
5
6
7
$ python backup_ver4.py
Enter a comment --> added new examples
Successful backup to /mnt/e/backup/20041208/082156_added_new_examples.zip

$ python backup_ver4.py
Enter a comment -->
Successful backup to /mnt/e/backup/20041208/082316.zip

如何工作

经过修改,程序现在工作了,相比版本二的改进:
使用raw_input函数得到用户的输入,通过len函数取得输入长度,判断是否有注释

进一步优化

交互性:使用-v选项来使程序更具交互性
参数传递:通过sys.argv列表获取文件和目录,使用list类提供的extend方法加入到source列表中
压缩命令:使用tar替代gzip命令,备份会更快更小(Linux/Unix一般默认可用,Windows可下载安装)。另外,使用Python标准库中的zipfile和tarfile更加理想,避免使用可能引发错误的os.system