博客开通很长时间了也没发个正式的文章,最近也是各种蛋疼,终于零零散散的把第九章的解析写完了,以后发博文的数量可能不多,但会尽量多写一些干货。
一至八章练习解析:传送门
第一题:
文件过滤. 显示一个文件的所有行, 忽略以井号( # )开头的行. 这个字符被用做Python , Perl, Tcl, 等大多脚本文件的注释符号. 附加题: 处理不是第一个字符开头的注释.
#!/usr/bin/env python # -*- coding:utf-8 -*- def count(filepath): f = open(filepath) for line in f: if line[0]!='#': print line if __name__=='__main__': filepath = raw_input(r'Please input file path:') count(filepath)
第二题:
文件访问. 提示输入数字 N 和文件 F, 然后显示文件 F 的前 N 行.
#!/usr/bin/env python # -*- coding:utf-8 -*- def output(filepath,linenum): f = open(filepath) for line in f: linenum -= 1 print line, if linenum <= 0: break if __name__=='__main__': filepath = raw_input(r'Please input file path:') linenum = input('Please input lines:') output(filepath,linenum)
第三题:
文件信息. 提示输入一个文件名, 然后显示这个文本文件的总行数。
#!/usr/bin/env python # -*- coding:utf-8 -*- def count(filepath): f = open(filepath) alllines = f.readlines() count_line = len(alllines) return count_line if __name__=='__main__': filepath = raw_input(r'Please input file path:') lines = count(filepath) print 'File has %d lines' % lines
第四题:
文件访问. 写一个逐页显示文本文件的程序. 提示输入一个文件名, 每次显示文本文件25 行, 暂停并向用户提示”按任意键继续.”, 按键后继续执行.
#!/usr/bin/env python # -*- coding:utf-8 -*- def readfile(filepath): count = 25 f = open(filepath) for line in f: if count > 0: print line count -= 1 else: count = 25 temp = raw_input('Please input anything to continue:') continue if __name__=='__main__': filepath = raw_input(r'Please input file path:') readfile(filepath)
第五题:
#!/usr/bin/env python # -*- coding:utf-8 -*- def readfile(filepath): f = open(filepath) for line in f: if int(line)>=90: print 'A' elif int(line)>=80: print 'B' elif int(line)>=70: print 'C' elif int(line)>=60: print 'D' else: print 'F' if __name__=='__main__': filepath = raw_input(r'Please input file path:') readfile(filepath)
第六题:
文件比较. 写一个比较两个文本文件的程序. 如果不同, 给出第一个不同处的行号和列号。
#!/usr/bin/env python # -*- coding:utf-8 -*- def comparefile(filepath1,filepath2): f1 = open(filepath1) f2 = open(filepath2) count_line = 0 for line1,line2 in zip(f1,f2): count_line += 1 if line1 != line2: count_list = 0 for i,j in zip(line1,line2): count_list += 1 if i != j: print 'The diffrent is %d line and %d list' % (count_line,count_list) break if count_list != 0: break if __name__=='__main__': filepath1 = raw_input(r'Please input first file path:') filepath2 = raw_input(r'Please input second file path:') comparefile(filepath1,filepath2) print 'Done!'
第七题:
解析文件。Win32用户,创建一个用来解析Windows.ini文件的程序。POSIX用户,创建一个解析/etc/serves文件的程序。其它平台的用户,写一个解析特定结构的系统配置文件的程序。
这里我就解析windows.ini文件吧,对linux还不是很熟。首先要了解一下ini文件的格式,ini文件主要包括这三个部分parameters、sections、comments,其中parameters是参数,形式为name=value;sections是节,由多个parameters组成,sections的名称有[]括起来;comments是注释,由;标识。解析的思路就是把parameters和sections的隶属关系准确的划分出来。
#-*- coding:utf-8 -*- def readini(filepath): sections = {} with open(filepath) as f: for item in f: if item.startswith(';'): continue if item.startswith('['): parameters = {} name = item[1:item.rfind(']')] sections[name] = parameters continue if item.count('=') > 0 and parameters != None: index = item.find('=') key = item[0:index] value = item[index+1:].strip() parameters[key] = value return sections if __name__ == '__main__': path = raw_input('Please input filepath:') result = readini(path) for key in result: if len(result[key])!=0: print '%s:' % key, for flag in result[key]: print '%s=%s ' % (flag,result[key][flag]), print 'n', else: print key
第八题:
模块研究。提取模块的属性资料,提示用户输入一个模块名,然后使用dir()和其他内建函数提取模块的属性,显示它们的名字、类型、值。
#-*- coding:utf-8 -*- def check_model(name): name = raw_input('module name: ') obj = __import__(name) ls = dir(obj) for item in ls: print 'name: ', item print 'type: ', type(getattr(obj, item)) print 'value: ', getattr(obj, item) print if __name__ == '__main__': name = raw_input('module name: ') check_model(name)
第九题:
Python文档字符串。进入Python标准库所在的目录,检查每个.py文件看是否有__doc__字符串,如果有,对其格式进行适当的整理归类。你
的程序执行完毕后,应该会生成一个漂亮的清单,里边列出哪些模块有文档字符串,以及文档字符串的内容,清单最后附上那些没有文档字符串模块的名字。
附加题:提取标准库中各模块内全部类和函数的文档。
os模块处理这类问题非常方便,此程序会在桌面生成一个doc.txt文件,文件中整洁的记录了每个文件__doc__字符串
#-*- coding:utf-8 -*- import os def check_doc(path): f = open(r'C:UsersAdministratorDesktopdoc.txt','w') f.write('__doc__ in there files:nnn') temp =[] for parent,localdir,filenames in os.walk(path): for file in filenames: print filenames if '__doc__' in dir(file): f.write(file+':'+file.__doc__+'nnn') else: temp.append(file) f.write('__doc__ not in there files:nnn') for i in temp: f.write(i+'nnn') if __name__ == '__main__': check_doc(r'D:python27Lib')
第十题:
家庭理财,创建一个家庭理财程序。你的程序需要处理储蓄、支票、金融市场,定期存款等多种账户。为每种账户提供一个菜单操作界面,要有存款、取款、借、贷等操作。另外还要提供一个取消操作选项。用户退出这个程序时相应的数据应保存到文件中。(出去备份的目的,程序运行的过程中也要备份)
本程序用shelve模块处理数据储存,用copy模块创建备份,详细信息请看注释:
#-*- coding:utf-8 -*- import os import shelve from shutil import copy def new_user(): '''用户新建程序,初始化数据''' name = raw_input('Please input your new name:') db = shelve.open(name+'.dat','c') db['M'] = 0 db['D'] = 0 db['W'] = 0 db['B'] = 0 db['L'] = 0 db.close() print 'Successful!' def account(order): '''数据处理函数,负责主要的数据操作''' name = raw_input('Please input your name:') name = name+'.dat' copy(name, name+'~') #创建备份文件 if name in os.listdir(os.getcwd()): db = shelve.open(name, 'c',True) money = input('Please input money:') if order == 'D': db['D'] = db['D']+money #存款 elif order == 'W': db['W'] = db['W']+money #取款 elif order == 'B': db['B'] = db['B']+money #借 elif order == 'L': db['L'] = db['L']+money #贷 db['M'] = db['D']-db['W']+db['B']-db['L'] #总金额 else: print 'Account not exite!' choice = raw_input('Dou you want to create a new account? Yes or No:') if choice == 'Yes': new_user() else: pass def help(): print ''' M :Money N :New user D :Deposit W :Withdraw money B :Borrow L :Loan C :Check account Q :Quit H :Help''' def check_account(): '''账户信息查看程序''' name = raw_input('Please input your name:')+'.dat' db = shelve.open(name, 'r') for item in db.items(): print '%-10s:%10d' % (item[0],item[1]) def menu(): '''菜单主程序''' print 'Welcome to Account System!' while True: order = raw_input('What do you want(H :help):') if order in 'MNCDWBLQH': if order == 'Q': #退出 break elif order == 'H': #查看帮助信息 help() elif order == 'N': #新建用户 new_user() elif order == 'C': #查看用户信息 check_account() else: account(order) else: print 'Invalid order,Please input again' print 'n' if __name__ == '__main__': menu()
第十一题:
(a)编写一个URL书签管理程序。使用基于文本的菜单,用户可以添加、修改或者删除书签数据项,书签数据项中包含站点名称、URL和一行简单说明(可
选)。另外提供检索功能,可以根据检索关键字在站点名称和URL两部分查找可能的匹配。程序退出时把数据保存到一个磁盘文件中去,再次执行时加载保存的数
据。
(b)改进(a)的方案,把书签输出到一个合法且语法正确的HTML文件中,这样用户就可以使用浏览器查看自己的书签清单。另外提供创建“文件夹”功能,对相关的书签进行分组管理。
附加题:请阅读Python的re模块了解有关的正则表达式的资料,使用正则表达式对用户输入的URL进行验证。
#-*- coding:utf-8 -*- import re def re_check(url): m = re.search(r"w{3}.w*.net|w{3}.w*.com|w{3}.w*.cn",url) #匹配符合条件的URL if m: return True else: return False def URL(order): '''功能函数,负责书签的曾、查、改、删''' if order == 'add': db = open('url.html','a') data = raw_input('Please input URL_name URL_value:').split() if re_check(data[1]): doc = raw_input('Please input simple txt:') db.write(r"<p><a href=http://"+data[1]+r">"+data[0]+r"</a>"+r"---------------->"+doc+r"</p>"+"n") #以html标签的形式写入,可被浏览器识别 else: print 'Error URL' elif order == 'del': db = open('url.html','r') data = db.readlines() db.close() name = raw_input('Please input the url name you want to del:') for line in data: if name in line: data.remove(line) break db = open('url.html','w') db.writelines(data) db.close() elif order == 'cha': db = open('url.html','r') data = db.readlines() db.close() name = raw_input('Please input the url name you want to change:') length = len(data) for i in range(length): if name in data[i]: temp = raw_input('Please input URL_name URL_value:').split() if re_check(temp[1]): doc = raw_input('Please input simple txt:') data[i] = r"<p><a href=http://"+temp[1]+r">"+temp[0]+r"</a>"+r"---------------->"+doc+r"</p>"+"n" else: print 'Error URL' break db = open('url.html','w') db.writelines(data) db.close() elif order == 'che': db = open('url.html','r') data = db.readlines() db.close() for line in data: print line def menu(): '''菜单程序''' print 'Welcome to URL Manage System!' while True: order = raw_input('What do you want(help: to view help txt):') if order in ['add','del','cha','che','help']: if order == 'help': help() else: URL(order) else: print 'Invalid order,Please input again' print 'n' def help(): print ''' add: Add del: Delete cha: Change che: Check help: Help ''' if __name__ == '__main__': '''同目录下会生成utl.html文件,储存书签,可直接用浏览器打开''' menu()
第十二题:
用户名和密码.回顾练习7-5,修改代码使之可以支持”上次登录时间”.请参阅time模块中的文档了解如何记录用户上次登录的时间.另外提供一个”系统管理员”,它可以导出所有用户的用户名,密码(如果想要的话,你可以把密码加密),以及”上次登录时间。
以前在CSDN写过跟这个非常类似的程序,请参阅:
Python–简单的用户管理系统 传送门
第十三题:
命令行参数。写一个程序,打印出所有的命令行参数。
#-*-coding:utf-8-*- import sys print str(sys.argv)
关于Python命令行参数也在原Blog做过总结:
Python 命令行解析工具 Argparse介绍(一) 传送门
Python 命令行解析工具 Argparse介绍(二) 传送门
第十四题:
这段代码是在网上copy的,自己写了半天感觉有点渣,一开始思路错了,这个写的特别好,就放在这里了。
# -*- coding:utf-8 -*- import sys import os def new_eval( num ): if num[1] == "+": return int( num[0] ) + int( num[2] ) elif num[1] == "-": return int( num[0] ) - int( num[2] ) elif num[1] == "*": return int( num[0] ) * int( num[2] ) elif num[1] == "/": return int( num[0] ) / int( num[2] ) elif num[1] == "%": return int( num[0] ) % int( num[2] ) elif num[1] == "**": return int( num[0] ) ** int( num[2] ) else: return "error operator" if __name__ == "__main__": if sys.argv[1:][0] == "print": with open( "result.txt" ) as fobj: print fobj.read() os.remove("result.txt") else: with open( "result.txt", "a+" ) as fobj: fobj.write("".join(sys.argv[1:])) fobj.write("n") fobj.write( str(new_eval( sys.argv[1:] ) )) fobj.write("n") print "the result is : %d" % ( new_eval( sys.argv[1:] ) )
第十五题:
复制文件。提示输入两个文件名(或者使用命令行参数),把第一个文件的内容复制到第二个文件中去。
#-*-coding:utf-8-*- import shutil filename1 = raw_input('Please input first filename:') filename2 = raw_input('Please input second filename:') shutil.copy(filename1,filename2)
第十六题:
文本处理。人们输入的字符常常超过屏幕的最大宽度,编写一个程序,在一个文本文件中查找长度大于80个字符的文本行。从最接80个字符的单词断行,把剩余的文件插入到下一行处。程序执行完毕后,应该没有超过80个字符的文本行了。
一开始以为需要用到正则表达式,因为需要匹配单词边界,后来发现只要查找最靠近80的空格就好了,要保持单词的完整性,部分说明请看注释:
#-*- coding:utf-8 -*- def check_text(): '''文档处理函数,对长度超过80的行截断''' f = open('1.txt','r') lines_1 = f.readlines() f.close() lines_2 = [] #将新生产的文档先储存在lines_2中 for line in lines_1: if len(line)>80: if line[80]==' ': #如果第81个位置是空格就不需要考虑单词边界的问题 lines_2.append(line[:80]+'n') lines_2.append(line[81:]) else: local = line[:80].rfind(' ') #否则查找最靠近第80个位置的空格截断,保持单词的完整性 lines_2.append(line[:local]+'n') lines_2.append(line[local+1:]) else: lines_2.append(line) f = open('1.txt','w') f.writelines(lines_2) f.close() if __name__ == '__main__': '''主函数''' while True: #循环检测每行的长度,直至长度全部小于或等于80 f = open('1.txt','r') lines = f.readlines() f.close() for line in lines: if len(line)>80: check_text() break else: break print 'Done!'
第十七题:
文本处理。创建一个原始的文本文件编辑器,你的程序应该是菜单驱动的,有如下这些选项:
1)创建文件(提示输入文件名和任意行的文本输入)
2)显示文件(把文件的内容显示到屏幕)
3)编辑文件(提示输入要修改的行,然后让用户进行修改)
4)保存文件
5)退出
#-*- coding:utf-8 -*- def Create(): '''Create a new file''' name = raw_input('Please input file name:') f = open(name,'w') print "Please input file content,'.' to end!" while True: line = raw_input()+'n' if line=='.n': f.close() break f.write(line) def Print(): name = raw_input('Please input file name:') f = open(name) for line in f: print line f.close() def Edit(): name = raw_input('Please input file name:') f = open(name) l = int(raw_input('Witch line do you want to check:')) lines = f.readlines() f.close() lines[l-1] = raw_input('Please input file content:')+'n' f = open(name,'w') f.writelines(lines) f.close() def help(): print ''' (C)reate File (P)rint File (E)dit File (Q)uit''' if __name__=='__main__': print 'Welcome to File Management System!' help() while True: order = raw_input('What do you want:') if order in 'CPEQ': if order == 'C': Create() elif order == 'P': Print() elif order == 'E': Edit() elif order == 'Q': break else: continue
第十八题:
搜索文件. 提示输入一个字节值(0 – 255)和一个文件名. 显示该字符在文件中出现的次数.
#-*- coding:utf-8 -*- def mycount(): num = 0 filename = raw_input('Please input file name:') mystring = raw_input('Please input your string:') f = open(filename) for line in f: num += line.count(mystring) return num if __name__ == '__main__': stringnum = mycount() print stringnum
第十九题:
创建文件. 创建前一个问题的辅助程序. 创建一个随机字节的二进制数据文件, 但 某一特定字节会在文件中出现指定的次数. 该程序接受三个参数:
1) 一个字节值( 0 – 255 ),
2) 该字符在数据文件中出现的次数, 以及
3) 数据文件的总字节长度.
#-*- coding:utf-8 -*- from random import randint def create(filename, value, total, maxlen): assert 0 <= value <= 255 ls = [chr(randint(0, 255)) for i in xrange(maxlen-total)] ch = chr(value) for i in xrange(total-ls.count(ch)): ls.insert(randint(0, len(ls)-1), ch) for i in xrange(maxlen - len(ls)): ls.insert(randint(0, len(ls)-1), chr(randint(0, value-1))) with open(filename, 'wb') as f: f.write(''.join(ls)) if __name__ == '__main__': filename = raw_input('file name: ') value = input('value: ') total = input('total: ') maxlen = input('max length of file: ') create(filename, value, total, maxlen)
第二十题:
压缩文件. 写一小段代码, 压缩/解压缩 gzip 或 bzip 格式的文件. 可以使用命令行下的 gzip 或 bzip2 以及 GUI 程序 PowerArchiver , StuffIt , 或 WinZip 来确认你的 Python支持这两个库.
#-*- coding:utf-8 -*- import gzip def encode(zipfile,otherfile): obj1 = open(otherfile,'rb') obj2 = gzip.open(zipfile,'wb') obj2.writelines(obj1) obj1.close() obj2.close() def decode(zipfile,otherfile): f = gzip.open(zipfile,'rb') file_content = f.read() obj = open('zip.txt','w') obj.writelines(file_content) f.close() if __name__ == '__main__': zipfile = raw_input('Please input zip file name:') otherfile = raw_input('Please input other file name:') encode(zipfile, otherfile) decode(zipfile, otherfile)
第二十一题:
ZIP 归档文件. 创建一个程序, 可以往 ZIP 归档文件加入文件, 或从中提取文件,有可能的话, 加入创建ZIP 归档文件的功能.
#-*- coding:utf-8 -*- import zipfile def add_file(): zip_name = raw_input('Please input zip file name:') file_name = raw_input('Please input other file name:') f = zipfile.ZipFile(zip_name,'a') f.write(file_name) def read_file(): zip_name = raw_input('Please input zip file name:') f = zipfile.ZipFile(zip_name,'r') for name in f.namelist(): file = open(name,'w') file.write(f.read(name)) file.close() f.close() if __name__=='__main__': add_file() read_file()
第二十二题:
ZIP归档文件。创建一个python脚本lszip.py,使它可以显示额外信息:压缩文件大小,每个文件的压缩比率(通过压缩前后文件大小),以及完成的time.ctime()时间戳,而不是只有日期和HH:MM。
#-*- coding:utf-8 -*- import zipfile import os import time filename = raw_input('zip file name: ') print 'zip file size: ', os.stat(filename).st_size f = zipfile.ZipFile(filename, 'r') print 'filenametdatetimetsizetcompress sizetrate' for info in f.infolist(): t = time.ctime(time.mktime(tuple(list(info.date_time) + [0, 0, 0]))) print '%st%st%dt%dt%.2f%%' % (info.filename, t, info.file_size, info.compress_size, float(info.compress_size) / info.file_size * 100) f.close()
第二十三题:
TAR归档文件。为TAR归档文件建立类似上个问题的程序。这两种文件的不同之处在于ZIP文件通常是压缩的,而TAR文件不是,只是在gzip和bzip2的支持下才能完成压缩工作。加入任意一种压缩格式支持。
import tarfile import time filename = raw_input('file name: ') if not tarfile.is_tarfile(filename): print "it's not a tarfile" else: tar = tarfile.open(filename, 'r') for info in tar: print info.name, info.size, time.ctime(info.mtime) tar.close()
第二十四题:
归档文件转换。参考前两个问题的解决方案,写一个程序,在ZIP和TAR/gzip或TAR/bzip2归档文件间移动文件。文件可能是已经存在的,必要时请创建文件。
#-*- coding:utf-8 -*- import tarfile import zipfile import os def movefile(src, dst, filename): if src.endswith('.zip') and dst.endswith(('.tar.gz', '.tgz', '.tbz', '.tar.bz2')): zipobj = zipfile.ZipFile(src, 'r') content = zipobj.read(filename) zipobj.close() with open(filename, 'w') as f: f.write(content) tar = tarfile.open(dst, 'r') ls = tar.getnames() tar.extractall() tar.close() mode = 'w:gz' if dst.endswith(('tar.gz', '.tgz')) else 'w:bz2' tar = tarfile.open(dst, mode) for name in ls+[filename]: tar.add(name) os.remove(name) tar.close() elif src.endswith(('.tar.gz', '.tgz', '.tbz', '.tar.bz2')) and dst.endswith('.zip'): tar = tarfile.open(src, 'r') tar.extract(filename) tar.close() zipobj = zipfile.ZipFile(dst, 'a') zipobj.write(filename) zipobj.close() os.remove(filename) if __name__ == '__main__': movefile('1.zip', '2.tar.gz', '1.txt') movefile('2.tar.gz', '1.zip', '2.txt')
第二十五题:
通用解压程序。创建一个程序,接受任意数目的归档文件以及一个目标目录为参数,归档文件格式可以是.zip、.tgz、.tar.gz、.gz、
bz2、.tar.bz2、.tbz中的一种或几种。程序会把第一个归档文件解压后放入目标目录,把其他归档文件解压后放入以对应文件名命名的目录下(不包括扩展名)。例如输入的文件名为header.txt.gz和data.tgz,目标目录为incoming,header.txt会被解压到incoming而data.tgz中的文件会被放入incoming/data。
#-*- coding:utf-8 -*- import tarfile import zipfile import os def decode_file(P,filename): if filename.endswith('.zip'): f = zipfile.ZipFile(P+filename,'r') for name in f.namelist(): file = open(P+name,'w') file.write(f.read(name)) file.close() f.close() elif filename.endswith(('.tgz', '.tar.gz', '.bz2', '.tbz', 'tar')): f = tarfile.open(P+filename,'r') f.extractall(path=P) f.close() if __name__ == '__main__': path = raw_input('Please input file path:') name = raw_input('Please input file name:') decode_file(path, name)
Pingback引用通告: 《Python核心编程》第十章练习解析 | Xman'Blog