python核心编程2 第九章 练习
9–1. 文件过滤. 显示一个文件的所有行, 忽略以井号( # )开头的行. 这个字符被用做Python , Perl, Tcl, 等大多脚本文件的注释符号.附加题: 处理不是第一个字符开头的注释.
filename = input("输入文件名:")
with open(filename) as f:
for i in f:
if i.startswith('#'):
continue
else:
print(i, end='')
9–2. 文件访问. 提示输入数字 N 和文件 F, 然后显示文件 F 的前 N 行.
num = int(input("输入数字:"))
filename = input("输入文件名:")
with open(filename) as f:
for i, j in enumerate(f):
if i == (num):
break
else:
print(j, end='')
9–3. 文件信息. 提示输入一个文件名, 然后显示这个文本文件的总行数.
filename = input('输入文件名:')
with open(filename) as f:
allline = f.readlines()
print(len(allline))
9–4. 文件访问.
写一个逐页显示文本文件的程序. 提示输入一个文件名, 每次显示文本文件的 25 行, 暂停并向用户提示"按任意键继续.", 按键后继续执行.
filename = input("输入文件名:")
num = 25
with open(filename) as f:
for i, j in enumerate(f, 1):
if i == num:
space = input("输入任意字符回车:")
num += 25
else:
print(j, end='')
9-5 考试成绩,改进你的考试成绩问题(练习5-3和6-4),要求能从多个文件中读入考试成绩。文件的数据格式由你自己决定。
filename = input("输入文件名:")
with open(filename) as f:
for i in f:
i = i.strip()
if int(i) < 60:
print("F")
elif int(i) < 70:
print("D")
elif int(i) < 80:
print("C")
elif int(i) < 90:
print("B")
elif int(i) <= 100:
print("A")
else:
print("%s不在范围" % i)
9–6. 文件比较. 写一个比较两个文本文件的程序. 如果不同, 给出第一个不同处的行号和列号.
def file(filename1, filename2):
with open(filename1) as f1:
f1alllines = f1.readlines() with open(filename2) as f2:
f2alllines = f2.readlines() minlen1 = min(len(f1alllines), len(f2alllines))
for i in range(minlen1):
if f1alllines[i] != f2alllines[i]: minlen2 = min(len(f1alllines[i]), len(f2alllines))
for j in range(minlen2):
if f1alllines[i][j] != f2alllines[i][j]:
return '不同行号: %s' % (i+1), '不同列号: %s' % (j+1)
return '文件相同' if __name__ == '__main__':
filename1 = input("输入文件名1:")
filename2 = input("输入文件名2:")
print(file(filename1, filename2))
9–7. 解析文件. Win32 用户: 创建一个用来解析 Windows .ini 文件的程序. POSIX 用户:创建一个解析 /etc/serves 文件的程序. 其它平台用户: 写一个解析特定结构的系统配置文件的程序.
windows = {}
with open(r'C:\Windows\win.ini') as f:
# print(f.readlines())
for line in f:
if line.startswith(';'):
continue
if line.startswith('['):
iterm = []
name = line[1: line.rfind(']')]
windows.setdefault(name, iterm)
continue
if '=' in line:
windows[name].append(line.strip())
print(windows)
9–8. 模块研究. 提取模块的属性资料. 提示用户输入一个模块名(或者从命令行接受输入).然后使用 dir() 和其它内建函数提取模块的属性, 显示它们的名字, 类型, 值.
m = input('输入模块名: ')
module = __import__(m)
ml = dir(module)
# print(ml)
for i in ml:
print('name: ', i)
print('type: ', type(getattr(module,i)))
print('value: ', getattr(module,i))
print('')
9–9. Python 文档字符串.
进入 Python 标准库所在的目录. 检查每个 .py 文件看是否有__doc__ 字符串, 如果有, 对其格式进行适当的整理归类. 你的程序执行完毕后, 应该会生成一个漂亮的清单. 里边列出哪些模块有文档字符串, 以及文档字符串的内容. 清单最后附上那些没有文档字符串模块的名字.附加题: 提取标准库中各模块内全部类(class)和函数的文档.
import os pymodules = {}
path = input("输入路径:")
pyfiles = [f for f in os.listdir(os.path.abspath(path)) if f.endswith('.py')] for f in pyfiles:
module = f[:-3]
pymodules.setdefault(module, '')
pyfile = os.path.join(path, f)
file = open(pyfile)
doc = False
for line in file:
if line.strip().startswith('"""') and line.strip().endswith('"""'):
pymodules[module] += line
file.close()
break
elif line.strip().startswith('"""') or line.strip().startswith('r"""') and len(line) > 3:
doc = True
pymodules[module] += line
continue
elif doc:
if line == '"""':
pymodules[module] += line
file.close()
doc = False
break
else:
pymodules[module] += line
else:
continue
file.close() hasdoc = []
nodoc = []
for module in pymodules:
if pymodules[module]:
hasdoc.append(module)
else:
nodoc.append(module) print('没有文档模块:')
for key in nodoc:
print(key) print("") print("有文档模块:")
for key in hasdoc:
print("%s:%s" % key, pymodules[key])
9-10.家庭理财。创建一个家庭理财程序。你的程序需要处理储蓄 、支票、金融市场 ,定期存款等多
种账户。为每种账户提供一个菜单操作界面 ,要有存款、取款、借、贷等操作 。另外还要提 一个取消操作选项 。用户退出这个程序时相关数据应该保存到文件里去 (出于备份的目的, 序执行过程中也要备份)。
# 函数思路不够用,只好用上类
import os
import json
import sys class Fm: def deposit(self):
"""存款"""
money = input("存款:")
if money == 'q':
self.saving()
else:
self.user_dict['余额'] += float(money)
with open('%s.json' % self.ID, 'w') as f:
json.dump(self.user_dict, f)
print("存款成功")
self.saving() def withdrawal(self):
"""取款"""
while True:
money = input("取款:")
if money == 'q':
self.saving()
else:
if float(money) <= self.user_dict['余额']:
self.user_dict['余额'] -= float(money)
with open('%s.json' % self.ID, 'w') as f:
json.dump(self.user_dict, f)
print("取款成功")
self.saving()
else:
print("取款金额超出余额,重新输入") def loan(self):
"""借款"""
money = input("存款:")
if money == 'q':
self.saving()
else:
self.user_dict['借款'] += float(money)
with open('%s.json' % self.ID, 'w') as f:
json.dump(self.user_dict, f)
print("借款成功")
self.saving() def credit(self):
"""贷款"""
money = input("贷款:")
if money == 'q':
self.saving()
else:
self.user_dict['贷款'] += float(money)
with open('%s.json' % self.ID, 'w') as f:
json.dump(self.user_dict, f)
print("贷款成功")
self.saving() def saving(self):
"""储蓄主菜单"""
showmenu = ("""
[1]存款
[2]取款
[3]借款
[4]贷款
[5]返回
[6]退出 请输入编号:""")
num = input(showmenu)
if num == '':
sys.exit()
elif num in '':
if num == '': self.deposit()
if num == '': self.withdrawal()
if num == '': self.loan()
if num == '': self.credit()
if num == '': self.main()
else:
print("输入有误") def main(self):
"""主菜单"""
showmenu = ("""
[1]储蓄
[2]支票(未写)
[3]金融市场(未写)
[4]定期存款(未写)
[5]退出 请输入编号:""")
num = input(showmenu)
if num == '':
sys.exit()
elif num in '':
if num == '': self.saving()
else:
print("输入有误") def registered(self):
"""注册"""
while True:
ID = input('ID:')
filename = '%s.json' % ID
if filename in os.listdir(os.getcwd()):
print("用户已存在")
else:
passwd = input('密码:')
name = input('姓名:')
registered_user = {}
registered_user['密码'] = passwd
registered_user['姓名'] = name
registered_user['余额'] = 0
registered_user['借款'] = 0
registered_user['贷款'] = 0
filename = open('%s.json' % ID, 'w')
json.dump(registered_user, filename)
filename.close()
print("注册成功")
self.user() def login(self):
"""登录"""
self.ID = input('ID:')
filename = '%s.json' % self.ID
if filename in os.listdir(os.getcwd()):
with open(filename) as user_file:
self.user_dict = json.load(user_file)
passwd = input("密码:")
if self.user_dict['密码'] == passwd:
print("登录成功")
print("---------------\n"
"姓名:{姓名}\n余额:{余额:.2f}\n借款:{借款:.2f}\n贷款:{贷款:.2f}\n"
"---------------".format(**self.user_dict))
self.main()
else:
print("密码错误")
else:
print("用户不存在") def user(self):
"""账号"""
showmenu = ("""
[1]注册
[2]登录
[3]退出 请输入编号:""")
num = input(showmenu)
while True:
if num == '':
break
elif num in '':
if num == '': self.registered()
if num == '':
if self.login():
self.main()
else:
print("输入有误") if __name__ == '__main__':
fm = Fm()
fm.user()
9–11. Web 站点地址.
a) 编写一个 URL 书签管理程序. 使用基于文本的菜单, 用户可以添加, 修改或者删除书签数据项. 书签数据项中包含站点的名称, URL 地址, 以及一行简单说明(可选). 另外提供检索功能,可以根据检索关键字在站点名称和 URL 两部分查找可能的匹配. 程序退出时把数据保存到一个磁盘文件中去; 再次执行时候加载保存的数据.
b)改进 a) 的解决方案, 把书签输出到一个合法且语法正确的 HTML 文件(.html 或 htm )中,这样用户就可以使用浏览器查看自己的书签清单. 另外提供创建"文件夹"功能, 对相关的书签进行分组管理.
附加题: 请阅读 Python 的 re 模块了解有关正则表达式的资料, 使用正则表达式对用户输入的 URL 进行验证.
import sys
import re regex = re.compile(r"^(((http|https)://)" # http、https
r"?([a-z]{2,}))\." # www
r"([a-z0-9]+)\." #
r"([a-z]{3}|([a-z]{3}\.[a-z]{2,4}))$") #com、com.cn filename = "bookmark.txt"
def add():
"""添加"""
urllist = []
while True:
url = input("输入地址[b:返回]:").strip()
if url == 'b':
main()
if regex.match(url):
urlname = input("输入名称:").strip()
description = input("简要说明:").strip()
urllist.append(urlname)
urllist.append(url)
urllist.append(description)
with open(filename, 'a+') as f:
f.write(str(urllist) + '\n')
print('添加成功')
else:
print("地址不规范") def modify():
"""修改"""
urllist = []
f = open(filename)
for i, j in enumerate(f):
urllist.append(eval(j))
print(i, j, end='')
f.close() while True:
num = input("修改编号[b:返回]:")
if num == 'b':
main()
if int(num) <= len(urllist):
url = input("输入地址:").strip()
if regex.match(url):
urlname = input("输入名称:").strip()
description = input("简要说明:").strip()
urllist[int(num)][0] = urlname
urllist[int(num)][1] = url
urllist[int(num)][2] = description
print("修改成功")
with open(filename, 'w') as urlfile:
for urlline in urllist:
urlfile.write(str(urlline) + '\n')
else:
print("地址不规范")
else:
print('输入有误') def delete():
"""删除"""
urllist = []
f = open(filename)
for i, j in enumerate(f):
urllist.append(eval(j))
print(i, j, end='')
f.close() while True:
num = input("\n删除编号[b:返回]:")
if num == 'b':
main()
if int(num) <= len(urllist):
del urllist[int(num)]
print('删除成功')
with open(filename, 'w') as urlfile:
for urlline in urllist:
urlfile.write(str(urlline) + '\n')
else:
print("输入有误") def find():
"""查找"""
urllist = []
while True:
name = input("查找内容[b:返回]:")
if name == 'b':
main()
with open(filename) as f:
for urlline in f:
urllist.append(eval(urlline))
if name in str(urllist):
for urlline in urllist:
if name in urlline:
print('%s\n名称:%s\n地址:%s\n说明:%s\n%s' %
('-'*20, urlline[0], urlline[1], urlline[2], '-'*20))
else:
print('书签不存在') def main():
"""主菜单"""
showmenu = ("""
[1]添加书签
[2]修改书签
[3]删除书签
[4]查找书签
[5]退出程序 请输入编号:""")
num = input(showmenu)
if num == '':
sys.exit()
elif num in '':
if num == '': add()
if num == '': modify()
if num == '': delete()
if num == '': find()
else:
print("输入有误") if __name__ == '__main__':
main()
9-12 用户名和密码。回顾练习7-5,修改代码使之可以支持“上次登录时间”。请参阅time模块中的文档了解如何记录用户上次登录的时间。另外提供一个系统管理员,他可以导出所有用户的用户名,密码(如需要可以加密),以及上次登录时间。
a)数据应保存在磁盘中,使用冒号:分隔,一次写入一行,例如“Joe:boohoo:953176591.145,文件中数据的行数应该等于你系统上的用户数。
b)进一步改进你的程序,不再一次写入一行,而使用pickle模块保存整个数据对象。请参阅pickle模块的文档了解如何序列化/扁平化对象,以及如何读写保存的对象。一般来说,这个解决方案的代码行数要比a)少;
c)使用shelve模块替换pickle模块,由于可以省去一些维护代码,这个解决方案的代码比b)的更少
from datetime import datetime
import hashlib, time, sys
import pickle as p
import shelve as s db = {} def newuser():
"""注册"""
value = []
prompt = 'login desired: '
while True:
name = input(prompt).lower()
if not name.isalnum() and '' in name:
print('name format error')
continue
else:
if name in db:
prompt = 'name taken, try another: '
continue
else:
break
pwd = input('login password desired:')
m = hashlib.md5()
m.update(pwd.encode(encoding='utf-8'))
value.append(m.hexdigest())
value.append(datetime.now())
value.append(time.time())
db[name] = value
print('new user is %s, register time is %s' % (name, db[name][1])) def olduser():
"""登录"""
name = input('Username:').lower()
pwd = input('Password:')
m = hashlib.md5()
m.update(pwd.encode(encoding='utf-8'))
passwd = db.get(name)
if passwd[0] == m.hexdigest():
newtimestamp = time.time()
newtime = datetime.now()
if newtimestamp - db[name][2] < 14400:
print('You already logged in at %s:' % db[name][1])
else:
passwd[1] = newtime
print('Welcome back %s, login time is %s' % (name, passwd[1]))
else:
print('Login incorrect') def removeuser():
"""删除"""
print(db)
name = input('Input a user name to remove:').lower()
if name in db:
db.pop(name)
print("Done")
else:
print('Input error') def getuser():
"""查询"""
while True:
name = input('login name desired:').lower()
if not name.isalnum() and '' in name:
print('name format error')
continue
else:
if name not in db:
print('User name is not in db')
answer = input('register a new user? y/n').lower()
if 'y' == answer:
newuser()
break
elif 'n' == answer:
break
else:
print('user name is already in db')
olduser()
break def textfile():
"""text"""
print(db)
f = open('account.txt', 'w')
f.write(str(db))
f.close() def picklefile():
"""pickle"""
accountfile = 'pickle.data'
f = open(accountfile, 'wb')
p.dump(db, f)
f.close() f = open(accountfile, 'rb')
accountdb = p.load(f)
print(accountdb) def shelvefile():
"""shelve"""
accountfile = 'shelve.data'
accountdb = s.open(accountfile, 'c')
accountdb['data'] = db
accountdb.close() accountdb = s.open(accountfile, 'r')
print(accountdb['data']) def adminlogin():
"""管理员"""
while True:
name = input('Username:').lower()
if not name.isalnum() and '' in name:
print('name format error')
continue
else:
pwd = input('Password:')
if name == 'root' and pwd == 'root':
print('Welcom admin')
if len(db) == 0:
print('There is nothing you can do')
showmenu()
else:
while True:
answer = input('Output all account? y/n').lower()
if 'y' == answer:
prompt = "(T)ext\n(P)ickle\n(S)helve\n\nEnter choice:"
choice = input(prompt).lower()
if choice in 'tps':
if choice == 't': textfile()
if choice == 'p': picklefile()
if choice == 's': shelvefile()
elif 'n' == answer:
print('Bye')
showmenu()
sys.exit()
else:
print('User name or password is wrong, input again') def showmenu():
"""功能"""
prompt = """
(N)ew User Login
(E)xisting User Login
(G)et user
(R)emove a existing user
(A)dmin Login
(Q)uit Enter choice: """ done = False
while not done:
chosen = False
while not chosen:
try:
choice = input(prompt).strip()[0].lower()
except (EOFError, KeyboardInterrupt):
choice = 'q'
print('\nYou picked: [%s]' % choice)
if choice not in 'negraq':
print('Invalid option, try again')
else:
chosen = True if choice == 'q': done = True
if choice == 'n': newuser()
if choice == 'e': olduser()
if choice == 'g': getuser()
if choice == 'r': removeuser()
if choice == 'a': adminlogin() if __name__ == '__main__':
showmenu()
9-14 记录结果。修改你的计算器程序(练习5-6)使之接受命令行参数。例如$ calc.py 1 + 2 只输出计算结果。另外,把每个表达式和它的结果写入到一个磁盘文件中,当使用下面的命令时 $ calc.py print 会把记录的内容显示到屏幕上,然后重置文件。这里是样例展示:
$ calc.py 1 + 2
3
$ calc.py 3 ^ 3
27
$ calc.py print
1 + 2
3
3 ^ 3
27
$ calc.py print
$
import sys, os if sys.argv[1] == 'print':
if os.path.exists(r'test.txt'):
f = open(r'test.txt', 'r')
for line in f:
print(line)
f.close()
else:
print('No file yet')
f = open(r'text.txt', 'w')
f.close()
else:
print(sys.argv[1], sys.argv[2], sys.argv[3])
a, b = sys.argv[1], sys.argv[3]
operation = sys.argv[2]
expression = sys.argv[1] + '' + sys.argv[2] + '' + sys.argv[3] + os.linesep
f = open(r'test.txt', 'a+')
f.write(expression)
if '+' == operation:
print(float(a) + float(b))
result = str(float(a) + float(b)) + os.linesep
f.write(result)
elif '-' == operation:
print(float(a) - float(b))
result = str(float(a) - float(b)) + os.linesep
f.write(result)
elif '**' == operation:
print(float(a) ** float(b))
result = str(float(a) ** float(b)) + os.linesep
f.write(result)
elif '/' == operation:
print(float(a) / float(b))
result = str(float(a) / float(b)) + os.linesep
f.write(result)
elif '%' == operation:
print(float(a) % float(b))
result = str(float(a) % float(b)) + os.linesep
f.write(result)
elif '*' == operation:
print(float(a) - float(b))
result = str(float(a) * float(b)) + os.linesep
f.write(result)
f.close()
9–15. 复制文件. 提示输入两个文件名(或者使用命令行参数). 把第一个文件的内容复制到第二个文件中去.
filename1 = input("输入文件名1:")
filename2 = input("输入文件名2:")
with open(filename1) as f:
filelines = f.readlines() with open(filename2, 'w') as f:
for fileline in filelines:
f.write(fileline)
9–16. 文本处理.
人们输入的文字常常超过屏幕的最大宽度. 编写一个程序, 在一个文本文件中查找长度大于 80 个字符的文本行. 从最接近 80 个字符的单词断行, 把剩余文件插入到下一行处.程序执行完毕后, 应该没有超过 80 个字符的文本行了.
filename = input("输入文件名:")
f1 = open(filename)
f = f1.readlines()
f1.close() content = []
for line in f:
if len(line) > 80:
num = list(line)
count = len(num) // 80
for i in range(count+1):
content.append("".join(num[:79]) + '\n')
num = num[79:]
content.append("".join(num))
else:
content.append(line) with open(filename, 'w') as f:
for fileline in content:
f.write(fileline)
print("Done")
9-17.文本处理 。创建一个原始的文本文件编辑器 。你的程序应该是菜单驱动的 ,有如下这些选项
1) 创建文件 (提示输入文件名和任意行的文本输入) :
2 ) 显示文件 (把文件的内容显示到屏幕):
3) 编辑文件 (提示输入要修改的行 ,然后让用户进行修改) :
4 ) 保存文件:
5 ) 退出。
import sys
import os def create():
"""创建文件"""
filename = input('输入文件名[b:返回]:')
if filename == 'b':
main()
while True:
text = input('输入内容[b:返回]:')
if text == 'b':
main()
with open(filename, 'a') as f:
f.write(text + '\n')
print("保存成功") def display():
"""显示文件"""
while True:
filename = input('输入文件名[b:返回]:')
if filename == 'b':
main()
with open(filename) as f:
for num, line in enumerate(f, 1):
print("第%d行:" % num, line, end='')
print('读取完毕') def edit():
"""编辑文件"""
filename = input('输入文件名[b:返回]:')
if filename == 'b':
main()
filelist = []
f = open(filename)
for num, line in enumerate(f, 1):
filelist.append(line)
print("第%d行:" % num, line, end='')
f.close()
print('读取完毕') while True:
num = input("输入修改的行编号[b:返回]:")
if num == 'b':
main()
if int(num)-1 <= len(filelist):
text = input("输入内容:")
filelist[int(num)-1] = text + '\n'
with open(filename, 'w') as f:
for line in filelist:
f.write(line)
else:
print("输入有误") def save():
"""保存文件"""
while True:
for_mat = input("查看文件格式(如: .txt)[b:返回]:")
if for_mat == 'b':
main()
if for_mat not in str(os.listdir(os.getcwd())):
print("格式不存在")
else:
for foldername, subfolders, filename in os.walk(os.getcwd()):
print("已保存%s文件:\n%s" % (for_mat, '-' * 20))
for file in filename:
if file.endswith(for_mat):
print(file)
print("%s" % '-' * 20) def main():
showmenu = ("""
[1]创建文件
[2]显示文件
[3]编辑文件
[4]保存文件
[5]退出 请输入编号:""")
while True:
num = input(showmenu)
if num == '':
sys.exit()
elif num in '':
if num == '': create()
if num == '': display()
if num == '': edit()
if num == '': save()
else:
print("输入有误") if __name__ == '__main__':
main()
9–18. 搜索文件. 提示输入一个字节值(0 - 255)和一个文件名. 显示该字符在文件中出现的次数.
num = int(input("输入数字(0-255):"))
filename = input("输入文件名:")
with open(filename) as f:
print(sum(line.count(chr(num)) for line in f))
9–20. 压缩文件.
写一小段代码, 压缩/解压缩 gzip 或 bzip 格式的文件. 可以使用命令行下的 gzip 或 bzip2 以及 GUI 程序 PowerArchiver , StuffIt , 或 WinZip 来确认你的 Python支持这两个库.
import gzip text = open(r'test.txt', 'rb')
gzipfile = gzip.open(r'test.txt.gz', 'wb')
gzipfile.writelines(text)
text.close()
gzipfile.close() gzipfile = gzip.open(r'test.txt.gz', 'rb')
text = open(r'test1.txt', 'wb')
content = gzipfile.read()
text.write(content)
gzipfile.close()
text.close()
9–21. ZIP 归档文件.
创建一个程序, 可以往 ZIP 归档文件加入文件, 或从中提取文件,有可能的话, 加入创建ZIP 归档文件的功能.
import zipfile, sys def archive_add():
"""归档、添加"""
filename = input("压缩文件名[b:返回]:")
if filename == 'b':
main()
sys.exit()
while True:
file = input("文件名[b:返回]:")
if file == 'b':
archive_add()
filezip = zipfile.ZipFile(filename, 'a')
filezip.write(file)
filezip.close()
print('Done') def extract():
"""提取"""
filename = input("压缩文件名[b:返回]:")
if filename == 'b':
main()
sys.exit()
filezip = zipfile.ZipFile(filename)
print(filezip.namelist())
filezip.close()
while True:
file = input("文件名[b:返回]:")
if file == 'b':
extract()
filezip = zipfile.ZipFile(filename)
filezip.extract(file)
filezip.close()
print('Done') def main():
menu = """
[1]归档、添加
[2]提取
[3]退出 请输入编号:""" while True:
num = input(menu)
if num == '':
break
elif num in '':
if num == '': archive_add()
if num == '': extract()
else:
print('输入有误') if __name__ == '__main__':
main()
9–22. ZIP 归档文件.
unzip -l 命令显示出的 ZIP 归档文件很无趣. 创建一个 Python脚本 lszip.py , 使它可以显示额外信息: 压缩文件大小, 每个文件的压缩比率(通过比较压缩前后文件大小), 以及完成的 time.ctime() 时间戳, 而不是只有日期和 HH:MM .
提示: 归档文件的 date_time 属性并不完整, 无法提供给 time.mktime() 使用....这由你自己决定.
import zipfile, time, os filename = input("Zip file name:")
print('Zip file size:%d bytes' % (os.stat(filename)).st_size)
z = zipfile.ZipFile(filename)
print('filename\t\t\tdatetime\t\t\tsize\tcompress size\trate')
for info in z.infolist():
t = time.ctime(time.mktime(tuple(list(info.date_time) + [0, 0, 0])))
print('%8s\t%s\t%4d\t\t%4d\t\t%.2f%%' % (info.filename, t, info.file_size, info.compress_size,
float(info.compress_size / info.file_size * 100) ))
z.close()
9–23. TAR 归档文件.
为 TAR 归档文件建立类似上个问题的程序. 这两种文件的不同之处在于 ZIP 文件通常是压缩的, 而 TAR 文件不是, 只是在 gzip 和 bzip2 的支持下才能完成压缩工作. 加入任意一种压缩格式支持.附加题: 同时支持 gzip 和 bzip2 .
import tarfile, os def compressfile(tarname, filename1, filename2):
t = tarfile.open(tarname, 'w:gz') #w.bz2
t.add(filename1)
t.add(filename2)
t.close() def extractfile(tarname):
t = tarfile.open(tarname, 'r')
t.extractall(os.getcwd())
t.close() if __name__ == '__main__':
compressfile(r'abc.tar.gz', r'a.txt', r'b.txt')#r'abc.tar.bz2'
extractfile(r'abc.tar.gz')#r'abc.tar.bz2'
9–24. 归档文件转换.
参考前两个问题的解决方案, 写一个程序, 在 ZIP (.zip) 和TAR/gzip (.tgz/.tar.gz) 或 TAR/bzip2 (.tbz/.tar.bz2) 归档文件间移动文件. 文件可能是已经存在的, 必要时请创建文件.
import zipfile, tarfile, os def movefile(compressfile1, compressfile2, file): if compressfile1.endswith('.zip') and compressfile2.endswith(('.tar.gz', '.tgz', '.tbz', '.tar.bz2')):
z = zipfile.ZipFile(compressfile1, 'a')
if file not in z.namelist():
f = open(file, 'w')
f.close()
z.write(file)
z.extract(file)
else:
z.extract(file)
z.close()
t = tarfile.open(compressfile2)
ls = t.getnames()
if file not in ls:
t.extractall()
t.close()
mode = 'w:gz' if compressfile2.endswith(('tar.gz', 'tgz')) else 'w:bz2'
t = tarfile.open(compressfile2, mode)
for name in ls + [file]:
t.add(name)
t.close()
os.remove(file)
t.close() elif compressfile1.endswith(('.tar.gz', '.tgz', '.tbz', '.tar.bz2')) and compressfile2.endswith('.zip'):
t = tarfile.open(compressfile1)
if file not in t.getnames():
f = open(file, 'w')
f.close()
else:
t.extract(file)
t.close()
z = zipfile.ZipFile(compressfile2, 'a')
if file not in z.namelist():
z.write(file)
z.close()
os.remove(file) if __name__ == '__main__':
compressfile1 = input('压缩文件名1:')
compressfile2 = input('压缩文件名2:')
file = input('文件名:')
movefile(compressfile1, compressfile2, file)
9–25. 通用解压程序.
创建一个程序, 接受任意数目的归档文件以及一个目标目录做为参数.归档文件格式可以是 .zip, .tgz, .tar.gz, .gz, .bz2, .tar.bz2, .tbz 中的一种或几种. 程序会把第一个归档文件解压后放入目标目录, 把其它归档文件解压后放入以对应文件名命名的目录下(不包括扩展名). 例如输入的文件名为 header.txt.gz 和 data.tgz , 目录为 incoming ,header.txt 会被解压到 incoming 而 data.tgz 中的文件会被放入 incoming/data .
import zipfile, tarfile, gzip, bz2, os def extract(dir1, dir2): filelist = os.listdir(dir1)
if filelist[0].endswith(('.tar.gz', '.tgz', '.tbz', '.tar.bz2')):
t = tarfile.open(os.path.join(dir1, filelist[0]))
t.extractall(dir2)
t.close() elif filelist[0].endswith('.gz'):
g = gzip.open(os.path.join(dir1, filelist[0]), 'rb')
ug = open(os.path.join(dir2, os.path.splitext(filelist[0])[0]), 'wb')
data = g.read()
ug.write(data)
ug.close()
g.close() elif filelist[0].endswith('.bz2'):
b = bz2.BZ2File(os.path.join(dir1, filelist[0]))
ub = open(os.path.join(dir2, os.path.splitext(filelist[0])[0]), 'wb')
data = b.read()
ub.write(data)
ub.close()
b.close() elif filelist[0].endswith('.zip'):
z = zipfile.ZipFile(os.path.join(dir1, filelist[0]))
z.extractall(dir2)
z.close() filelist.remove(filelist[0]) for file in filelist: dirname = os.path.splitext(file)[0] if dirname in os.listdir(dir2):
dirname = os.path.join(dir2, dirname, str(filelist.index(file)))
else:
dirname = os.path.join(dir2, dirname)
os.makedirs(dirname) if file.endswith(('.tar.gz', '.tgz', '.tbz', '.tar.bz2')):
t = tarfile.open(os.path.join(dir1, file))
t.extractall(dirname)
t.close() elif file.endswith('.gz'):
g = gzip.open(os.path.join(dir1, file), 'rb')
ug = open(os.path.join(dirname, os.path.splitext(file)[0]), 'wb')
data = g.read()
ug.write(data)
ug.close()
g.close() elif file.endswith('.bz2'):
b = bz2.BZ2File(os.path.join(dir1, file))
ub = open(os.path.join(dirname, os.path.splitext(file)[0]), 'wb')
data = b.read()
ub.write(data)
ub.close()
b.close() elif file.endswith('.zip'):
z = zipfile.ZipFile(os.path.join(dir1, file))
z.extractall(dirname)
z.close() if __name__ == '__main__':
dir1 = os.path.abspath(input('Path1: '))
dir2 = os.path.abspath(input('Path2: '))
extract(dir1, dir2)
python核心编程2 第九章 练习的更多相关文章
- 【7】python核心编程 第十一章-函数和函数式编程
1.*函数(与方法)装饰器 装饰器背后的主要动机源自python 面向对象编程.装饰器是在函数调用之上的修饰.这些修饰 仅是当声明一个函数或者方法的时候,才会应用的额外调用. 装饰器的语法以@开头,接 ...
- 【1】python核心编程 第三章
1.继续( \ ) 有两种例外情况一个语句不使用反斜线也可以跨行.在使用闭合操作符时,单一语句可以跨多行,例如:在含有小括号.中括号.花括号时可以多行书写.另外就是三引号包括下的字符串也可以跨行书写 ...
- python核心编程-第三章-习题
1.这是python的语言特性,python先创建对象,在给变量赋值时,不需要定义变量的名称和类型,它实际是用变量引用对象.变量类型在给变量赋值时自动声明 2.原因类似变量无须声明类型 3.pytho ...
- python核心编程-第三章-个人笔记
1.语句和语法 (1)反斜杠"\"表示语句继续.python良好的编程习惯是一行最后不超过80个字符,一行字符过多时便须用到反斜杠换行继续该语句. PS:在使用小括号.中括号.大括 ...
- Python核心编程笔记 第二章
2.1 程序输出:print语句 可以使用print语句显示变量的字符串表示,或者仅用变量名查看该变量的原始值. 2.2 程序输出和raw_input()内建函数 ...
- [Python核心编程] 第1章 欢迎来到Python世界
什么是Python Python的起源 Python的特点 下载Python 安装Python 运行Python Python文档 比较Python 其他实现 1.什么是Python ...
- python核心编程第六章练习6-14
随机数.设计一个“石头.剪子.布”游戏,有时又叫“Rochambeau”,你小时候可能玩过,下面是规则.你和你的对手,在同一时间做出特定的手势,必须是下面一种:石头.剪子.布.胜利者从下面的规则产生, ...
- python核心编程第六章练习6-13
6-13.字符串.string模块包含三个函数,atoi(),atol()和atof(),他们分别负责把字符串转换成整型.长整型和浮点型数字.从Python 1.5起,Python的内建函数int() ...
- python核心编程第六章练习6-10
6-10.字符串.写一个函数,返回一个跟输入字符串相似的字符串,要求字符串的大小写反转,比如,输入“Mr.Ed”,应该返回“mR.eD”作为输出.[答案]代码如下: #!/usr/bin/env py ...
随机推荐
- 引爆你的Javascript代码进化 (转)
转自 海玉的博客 方才在程序里看到一段JS代码,写法极为高明,私心想着若是其按照规范来写,定可培养对这门语言的理解,对JS编程能力提高必是极好的.说人话:丫代码写的太乱,看的窝火! 最近闲暇无事,准备 ...
- Chrome+ProxySwitchySharp+Putty
好不容易写一个不编程的随笔了. 题目写出来,目的就已经很明确了,我就不详细解释原因了. 其实一年前多就已经配置成功了,写这篇随笔主要是给自己做一个备份,如果顺便能帮助其他人,也算功德无量了. 我就从最 ...
- 【MATLAB】R2017b两个镜像文件如何安装
1.采用DEAMON TOOLS加载镜像1. 2.当安装过程中弹出[请插入DVD2]时,在原来的盘符上面右键点击[装载],选择DVD2的镜像文件.在安装程序处选择[继续]即可正常安装.
- maven学习(一)setting.xml配置文件详解
maven环境搭建: 1.官网下载zip包,解压至任意目录(如:E:\wly\apache-maven-3.2.5) 2.环境变量MAVEN_HOME(E:\wly\apache-maven-3.2. ...
- 使用 yield生成迭代对象函数
https://www.cnblogs.com/python-life/articles/4549996.html https://www.liaoxuefeng.com/wiki/001431608 ...
- day2 数据结构和一些基础知识
请查看我的云笔记链接: http://note.youdao.com/noteshare?id=4171342601326695ec87866e1cc3e410&sub=20CFB149543 ...
- February 27 2017 Week 9 Monday
All the bright precious things fade so fast. 所有的光鲜靓丽都敌不过时间. Try to make some things endurable and et ...
- Python3基本数据类型(六、字典)
一.集合介绍 Python set是基本数据类型的一种集合类型,它有可变集合(set())和不可变集合(frozenset)两种.集合是一个无序的,不重复的数据组合,主要作用为:去重(把一个列表变成集 ...
- Selenium入门21 Select操作
select元素有单独的类:from selenium.webdriver.support.ui import Select 界面上选出select元素后,Select(select)进行类型转换就可 ...
- TCP的建立和关闭
一.TCP头信息 简单的至少应该知道,源端口,目的端口,序号,确认号,标志位,校验和 二.TCP的建立 1.客户端将SYN标志位置1,同时生成随机的序号,确认号是0. 2.服务器接收到SYN,知道有人 ...