《Python核心编程》第9章 习题

9–1. 文件过滤. 显示一个文件的所有行, 忽略以井号( # )开头的行. 这个字符被用做Python , Perl, Tcl, 等大多脚本文件的注释符号.附加题: 处理不是第一个字符开头的注释.

[python]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. f=open('test.txt','r')  
  2. for eachline in f:  
  3.     if eachline.startswith('#'):  
  4.         continue  
  5.     elif '#' in eachline:  
  6.         loc=eachline.find('#')  
  7.         print eachline[:loc]  
  8.     else:  
  9.         print eachline,  
  10. f.close()  
9–2. 文件访问. 提示输入数字 N 和文件 F, 然后显示文件 F 的前 N 行.
[python]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. N=int(raw_input('pls input a number:'))  
  2. F=raw_input('pls input a file name:')  
  3. f=open(F,'r')  
  4. alllines=f.readlines()  
  5. f.close()  
  6. for i in range(N):  
  7.     print alllines[i],  
9–3. 文件信息.  提示输入一个文件名, 然后显示这个文本文件的总行数.
[python]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. F=raw_input('pls input a file name:')  
  2. f=open(F,'r')  
  3. alllines=f.readlines()  
  4. f.close()  
  5. print len(alllines)  
9–4. 文件访问. 

写一个逐页显示文本文件的程序. 提示输入一个文件名, 每次显示文本文件的 25 行, 暂停并向用户提示"按任意键继续.", 按键后继续执行.

[python]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. import os  
  2. F=raw_input('pls input a file name:')  
  3. n=0  
  4. f=open(F,'r')  
  5. for i in f:  
  6.     print i,  
  7.     n+=1  
  8.     if n==25:  
  9.         n=0  
  10.         os.system('pause')  
  11. f.close()  
9-5 考试成绩,改进你的考试成绩问题(练习5-3和6-4),要求能从多个文件中读入考试成绩。文件的数据格式由你自己决定。

[python]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. f=open('test.txt','r')  
  2. scores=[]  
  3. for i in f:  
  4.     if 0<=int(i.strip())<=100:  
  5.         scores.append(int(i.strip()))  
  6.     if int(i.strip())<60:  
  7.          print 'score is F' ,i  
  8.     elif 60<=int(i.strip())<=69:  
  9.          print 'score is D',i  
  10.     elif 70<=int(i.strip())<=79:  
  11.          print 'score is C',i  
  12.     elif 80<=int(i.strip())<=89:  
  13.          print 'score is B',i  
  14.     elif 90<=int(i.strip())<=100:  
  15.          print 'score is A',i  
  16.     else:  
  17.          print 'score wrong,please input again',i  
  18. f.close()  
  19. print 'average score is %f' %(sum(scores)//len(scores))  
9–6. 文件比较.  写一个比较两个文本文件的程序. 如果不同, 给出第一个不同处的行号和列号.
[python]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. F1=raw_input('pls input a file name:')  
  2. F2=raw_input('pls input a file name:')  
  3. f1=open(F1,'r')  
  4. f1alllines=f1.readlines()  
  5. f1.close()  
  6. f2=open(F2,'r')  
  7. f2alllines=f2.readlines()  
  8. f2.close()  
  9. len1=len(f1alllines)  
  10. len2=len(f2alllines)  
  11. smallfile=len1 if len1<=len2 else len2  
  12. for i in range(smallfile):  
  13.     if cmp(f1alllines[i],f2alllines[i])!=0:  
  14.         print 'row is %d ' %(i+1)  
  15.         len3=len(f1alllines[i])  
  16.         len4=len(f2alllines[i])  
  17.         smallstr=len3 if len3<=len4 else len4  
  18.         for j in range(smallstr):  
  19.             if cmp(f1alllines[i][j],f2alllines[i][j])!=0:  
  20.                 print 'column is %d ' %(j+1)  
  21.                 break  
  22.         break  
  23. else:  
  24.     if len1==len2:  
  25.         print '2 files equal'  
  26.     else:  
  27.         print 'row is %d ' %(i+2)  
9–7. 解析文件.  Win32 用户: 创建一个用来解析 Windows .ini 文件的程序. POSIX 用户:创建一个解析 /etc/serves 文件的程序. 其它平台用户: 写一个解析特定结构的系统配置文件的程序.
[python]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. option={}  
  2. f=open(r'c:\windows\win.ini')  
  3. for line in f:    
  4.     if line.startswith(';'):    
  5.         continue    
  6.     if line.startswith('['):  
  7.         iterm=[]  
  8.         name = line[1:line.rfind(']')]    
  9.         option.setdefault(name,iterm)  
  10.         continue    
  11.     if '=' in line:    
  12.         option[name].append(line.strip())   
  13. print option    
9–8. 模块研究.  提取模块的属性资料. 提示用户输入一个模块名(或者从命令行接受输入).然后使用 dir() 和其它内建函数提取模块的属性, 显示它们的名字, 类型, 值.
[python]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. m=raw_input('pls input a module name: ')  
  2. module=__import__(m)  
  3. ml=dir(module)  
  4. print ml  
  5. for i in ml:  
  6.     print 'name: ',i  
  7.     print 'type: ',type(getattr(module,i))  
  8.     print 'value: ',getattr(module,i)  
  9.     print  
9–9. Python 文档字符串. 

进入 Python 标准库所在的目录. 检查每个 .py 文件看是否有__doc__ 字符串, 如果有, 对其格式进行适当的整理归类. 你的程序执行完毕后, 应该会生成一个漂亮的清单. 里边列出哪些模块有文档字符串, 以及文档字符串的内容. 清单最后附上那些没有文档字符串模块的名字.附加题: 提取标准库中各模块内全部类(class)和函数的文档.

[python]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. import os  
  2. pymodules={}  
  3. path=r'D:\Program Files\Python27\Lib'  
  4. pyfiles=[f for f in os.listdir(path) if f.endswith('.py')]  
  5. for f in pyfiles:  
  6.     module=f[:-3]  
  7.     pymodules.setdefault(module,'')  
  8.     pyfile=path+os.sep+f  
  9.     fobj=open(pyfile)  
  10.     doc=False  
  11.     for line in fobj:  
  12.         if line.strip().startswith('"""''"""') and line.strip().endswith('"""'):  
  13.             pymodules[module]+=line  
  14.             fobj.close()  
  15.             break  
  16.         elif (line.strip().startswith('"""''"""') or line.strip().startswith('r"""')) and len(line)>3: 
  17.             doc=True 
  18.             pymodules[module]+=line 
  19.             continue 
  20.         elif doc: 
  21.             if line=='"""':  
  22.                 pymodules[module]+=line  
  23.                 fobj.close()  
  24.                 doc=False  
  25.                 break  
  26.             else:  
  27.                 pymodules[module]+=line  
  28.         else:  
  29.             continue  
  30.     else:  
  31.         fobj.close()  
  32.            
  33. hasdoc=[]  
  34. nodoc=[]  
  35. for module in pymodules:  
  36.     if pymodules[module]:  
  37.         hasdoc.append(module)  
  38.     else:  
  39.         nodoc.append(module)  
  40.   
  41. print 'module has no doc:'  
  42. for key in nodoc:  
  43.     print key,  
  44. print '\n'  
  45. print 'module has doc:'  
  46. for key in hasdoc:  
  47.     print 'module:',key  
  48.     print 'doc:',pymodules[key]  
9-10 不会

9–11. Web 站点地址.
a) 编写一个 URL 书签管理程序. 使用基于文本的菜单, 用户可以添加, 修改或者删除书签数据项. 书签数据项中包含站点的名称, URL 地址, 以及一行简单说明(可选). 另外提供检索功能,可以根据检索关键字在站点名称和 URL 两部分查找可能的匹配. 程序退出时把数据保存到一个磁盘文件中去; 再次执行时候加载保存的数据.
b)改进 a) 的解决方案, 把书签输出到一个合法且语法正确的 HTML 文件(.html 或 htm )中,这样用户就可以使用浏览器查看自己的书签清单. 另外提供创建"文件夹"功能, 对相关的书签进行分组管理.
附加题: 请阅读 Python 的 re 模块了解有关正则表达式的资料, 使用正则表达式对用户输入的 URL 进行验证.

[python]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. import re,os  
  2.   
  3. def checkurl(url):      
  4.     regex = re.compile(  
  5.             r'^(?:http|ftp)s?://' # http:// or https://  
  6.             r'(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+(?:[A-Z]{2,6}\.?|[A-Z0-9-]{2,}\.?)|' #domain...  
  7.             r'localhost|' #localhost...  
  8.             r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})' # ...or ip  
  9.             r'(?::\d+)?' # optional port  
  10.             r'(?:/?|[/?]\S+)$', re.IGNORECASE)  
  11.     if regex.match(url):  
  12.         return True  
  13.     else:  
  14.         return False  
  15.   
  16. def geturl():  
  17.     name=raw_input('pls input a url name:')      
  18.     while 1:  
  19.         url=raw_input('pls input a url address:')  
  20.         if checkurl(url):  
  21.             break  
  22.         else:  
  23.             print 'wrong url format,pls input again'  
  24.     mark=raw_input('pls input a url mark:')  
  25.     folder=raw_input('pls input a url folder:')  
  26.     return (name,url,mark,folder)  
  27.   
  28. def load(filename):  
  29.     f=open(filename,'a+')  
  30.     bmlist=f.readlines()  
  31.     f.close()  
  32.     return bmlist  
  33.   
  34. def save(bmlist,filename):  
  35.     f=open(filename,'w+')  
  36.     for line in bmlist:  
  37.         if len(line)==0:  
  38.             continue  
  39.         f.write(line)  
  40.     f.close()  
  41.   
  42. def add(bmlist,name,url,mark,folder='default'):  
  43.     bookmark=''  
  44.     bookmark=name+';'+url+';'+mark+';'+folder+os.linesep  
  45.     if bookmark not in bmlist:  
  46.         bmlist.append(bookmark)  
  47.   
  48. def modify(bmlist,index,name,url,mark,folder):  
  49.     bookmark=''  
  50.     bookmark=name+';'+url+';'+mark+';'+folder+os.linesep  
  51.     bmlist[index]=bk  
  52.   
  53. def delbm(bmlist,index):  
  54.     bmlist.pop(index)  
  55.   
  56. def findbk(bmlist,fname,furl):  
  57.     for i,item in enumerate(bmlist):  
  58.         (name,url,mark,folder)=item.split(';')  
  59.         if fname and furl:  
  60.             if (fname in name) and (furl in url):  
  61.                 return i  
  62.         if fname and (fname in name):  
  63.             return i  
  64.         if furl and (furl in url):  
  65.             return i  
  66.     else:  
  67.         return -1  
  68.   
  69. def output2html(bmlist):     
  70.     for i,item in enumerate(bmlist):  
  71.         (name, url, mark, folder) = item.split(';')  
  72.         os.mkdir(folder.strip())  
  73.         filename=name.strip()+'.html'  
  74.         f=open(filename,'w+')  
  75.         fmt = '%d\t%s\t<a href=%s>%s</a>\t%s\t%s<br>'  
  76.         f.write('<html><head><title>bookmark</title></head><body>')   
  77.         content = fmt % (i+1, name, r'http:\\' + url, url, mark, folder)     
  78.         f.write(content)    
  79.         f.write('</body></html>')  
  80.         f.close()  
  81.         os.rename(filename,folder.strip()+os.sep+filename)  
  82.   
  83. bmlist=load(r'url.txt')  
  84. print bmlist  
  85. while True:  
  86.     print '0. quit'  
  87.     print '1. add a url bookmark'  
  88.     print '2. modify a url bookmark'  
  89.     print '3. delete a url bookmark'  
  90.     print '4. find a url bookmark'  
  91.     print '5. output url bookmark as html'  
  92.     print '\n'  
  93.   
  94.     iInput = input("please input operation num: ")  
  95.     if (0 == iInput):  
  96.         save(bmlist,r'url.txt')  
  97.         break  
  98.     elif (iInput<0 or iInput>5):  
  99.         print 'Error input operation, try agin. 0 operation is quit\n'  
  100.         continue  
  101.     elif 1 == iInput:  
  102.         data=geturl()  
  103.         add(bmlist,*data)  
  104.         print bmlist  
  105.     elif 2 == iInput:  
  106.         index=int(raw_input('bookmark index:'))  
  107.         data=geturl()  
  108.         modify(bmlist,index,*data)  
  109.         print bmlist  
  110.     elif 3 == iInput:  
  111.         index=int(raw_input('bookmark index:'))  
  112.         delbm(bmlist,index)  
  113.         print bmlist  
  114.     elif 4 == iInput:  
  115.         name=raw_input('url name:')  
  116.         url=raw_input('url address:')  
  117.         index=findbk(bmlist,name,url)  
  118.         if index==-1:  
  119.             print 'not found'  
  120.         else:  
  121.             print bmlist[index]  
  122.     elif 5 == iInput:  
  123.         output2html(bmlist)  
9-12 用户名和密码。回顾练习7-5,修改代码使之可以支持“上次登录时间”。请参阅time模块中的文档了解如何记录用户上次登录的时间。另外提供一个系统管理员,他可以导出所有用户的用户名,密码(如需要可以加密),以及上次登录时间。

a)数据应保存在磁盘中,使用冒号:分隔,一次写入一行,例如“Joe:boohoo:953176591.145,文件中数据的行数应该等于你系统上的用户数。

b)进一步改进你的程序,不再一次写入一行,而使用pickle模块保存整个数据对象。请参阅pickle模块的文档了解如何序列化/扁平化对象,以及如何读写保存的对象。一般来说,这个解决方案的代码行数要比a)少;

c)使用shelve模块替换pickle模块,由于可以省去一些维护代码,这个解决方案的代码比b)的更少。

[python]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. from datetime import datetime  
  2. import hashlib,os  
  3. import pickle as p  
  4. import shelve as s  
  5.    
  6. db={}  
  7. def newuser():  
  8.     value=[]  
  9.     prompt='login name desired again: '  
  10.     while True:  
  11.         name=raw_input(prompt).lower()  
  12.         if not name.isalnum() and '' in name:  
  13.             print 'name format error'  
  14.             continue  
  15.         else:  
  16.             if db.has_key(name):  
  17.                 prompt='name taken,try another: '  
  18.                 continue  
  19.             else:  
  20.                 break  
  21.     pwd=raw_input('login passwd desired: ')  
  22.     m=hashlib.md5()  
  23.     m.update(pwd)  
  24.     value.append(m.hexdigest())  
  25.     value.append(datetime.now())  
  26.     db[name]=value  
  27.     print 'new user is %s, register time is %s' %(name,db[name][1])  
  28.   
  29. def olduser():  
  30.     name=raw_input('login name desired again: ').lower()  
  31.     pwd=raw_input('login passwd desired: ')  
  32.     m=hashlib.md5()  
  33.     m.update(pwd)  
  34.     passwd=db.get(name)  
  35.     if passwd[0]==m.hexdigest():  
  36.         newtime=datetime.now()  
  37.         if (newtime-db[name][1]).days==0 and (newtime-db[name][1]).seconds<14400:  
  38.             print 'you already logged in at %s: ' %(db[name][1])  
  39.         else:  
  40.             passwd[1]=newtime  
  41.             print 'welcome back %s, login time is %s' %(name,passwd[1])  
  42.           
  43.     else:  
  44.         print 'login incorrect'  
  45.   
  46. def removeuser():  
  47.     print db  
  48.     name=raw_input('input a user name to remove: ').lower()  
  49.     if name in db:  
  50.         db.pop(name)  
  51.     else:  
  52.         print 'input error'  
  53.   
  54. def userlogin():  
  55.     while True:  
  56.         name=raw_input('login name desired: ').lower()  
  57.         if not name.isalnum() and '' in name:  
  58.             print 'name format error'  
  59.             continue  
  60.         else:  
  61.             if not db.has_key(name):  
  62.                 print 'user name is not in db'  
  63.                 answer=raw_input('register a new user? y/n').lower()  
  64.                 if 'y'==answer:  
  65.                     newuser()  
  66.                     break  
  67.                 elif 'n'==answer:  
  68.                     break  
  69.             else:  
  70.                 print 'user name is already in db'  
  71.                 olduser()  
  72.                 break  
  73.   
  74. def outputA():  
  75.     print db  
  76.     f=open('account.txt','w')  
  77.     for key in db:  
  78.         user=key+':'+db[key][0]+':'+str(db[key][1])+os.linesep  
  79.         f.write(user)  
  80.     f.close()  
  81.   
  82. def outputB():  
  83.     accountfile='pickle.data'  
  84.     f=open(accountfile,'w')  
  85.     p.dump(db,f)  
  86.     f.close()  
  87.   
  88.     f=open(accountfile)  
  89.     accountdb=p.load(f)  
  90.     print accountdb  
  91.   
  92. def outputC():  
  93.     accountfile='shelve.data'  
  94.     accountdb=s.open(accountfile,'c')  
  95.     accountdb['data']=db  
  96.     accountdb.close()  
  97.   
  98.     accountdb=s.open(accountfile,'r')  
  99.     print accountdb['data']  
  100.   
  101. def adminlogin():  
  102.     while True:  
  103.         name=raw_input('login name desired: ').lower()  
  104.         if not name.isalnum() and '' in name:  
  105.             print 'name format error'  
  106.             continue  
  107.         else:  
  108.             pwd=raw_input('login passwd desired: ')  
  109.             if name=='root' and pwd=='root':  
  110.                 print 'welcom admin'  
  111.                 break  
  112.             else:  
  113.                 print 'user name or passwd is wrong,input again'  
  114.     if len(db)==0:  
  115.         print 'there is nothing you can do'  
  116.     else:  
  117.         answer=raw_input('output all account? y/n').lower()  
  118.         if 'y'==answer:  
  119.             #outputA()  
  120.             #outputB()  
  121.             outputC()  
  122.         elif 'n'==answer:  
  123.             print 'bye'     
  124.   
  125. def showmenu():  
  126.     prompt=""" 
  127.     (A)dmin Login 
  128.     (U)ser Login 
  129.     (R)emove a existing user 
  130.     (Q)uit 
  131.      Enter choice:"""  
  132.   
  133.     done=False  
  134.     while not done:  
  135.         chosen=False  
  136.         while not chosen:  
  137.             try:  
  138.                 choice=raw_input(prompt).strip()[0].lower()  
  139.             except (EOFError,keyboardInterrupt):  
  140.                 choice='q'  
  141.             print '\nYou picked: [%s]' % choice  
  142.             if choice not in 'aurq':  
  143.                 print 'invalid option,try again'  
  144.             else:  
  145.                 chosen=True  
  146.   
  147.         if choice=='q':  
  148.             done=True  
  149.         if choice=='r':  
  150.             removeuser()  
  151.         if choice=='u':  
  152.             userlogin()  
  153.         if choice=='a':  
  154.             adminlogin()  
  155.   
  156. if __name__=='__main__':  
  157.     showmenu()  
9–13. 命令行参数
a) 什么是命令行参数, 它们有什么用?

命令行参数是调用某个程序时除程序名以外的其他参数。命令行参数使程序员可以在启动一个程序时对程序行为作出选择。
b) 写一个程序, 打印出所有的命令行参数.

[python]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. import sys  
  2. print str(sys.argv)  
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

[python]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. import sys,os  
  2.   
  3. if sys.argv[1]=='print':  
  4.     if os.path.exists(r'test.txt'):  
  5.         f=open(r'test.txt','r')  
  6.         for line in f:  
  7.             print line  
  8.         f.close()  
  9.     else:  
  10.         print 'no file yet'  
  11.     f=open(r'test.txt','w')  
  12.     f.close()  
  13. else:  
  14.     print sys.argv[1],sys.argv[2],sys.argv[3]  
  15.     a,b=sys.argv[1],sys.argv[3]  
  16.     operation=sys.argv[2]  
  17.     expression=sys.argv[1]+''+sys.argv[2]+''+sys.argv[3]+os.linesep  
  18.     f=open(r'test.txt','a+')  
  19.     f.write(expression)  
  20.     if '+' == operation:  
  21.         print float(a)+float(b)  
  22.         result=str(float(a)+float(b))+os.linesep+os.linesep  
  23.         f.write(result)  
  24.     elif '-' == operation:  
  25.         print float(a)-float(b)  
  26.         result=str(float(a)-float(b))+os.linesep+os.linesep  
  27.         f.write(result)  
  28.     elif '**' == operation:  
  29.         print float(a)**float(b)  
  30.         result=str(float(a)**float(b))+os.linesep+os.linesep  
  31.         f.write(result)  
  32.     elif '/' == operation:  
  33.         print float(a)/float(b)  
  34.         result=str(float(a)/float(b))+os.linesep+os.linesep  
  35.         f.write(result)  
  36.     elif '%' == operation:  
  37.         print float(a)%float(b)  
  38.         result=str(float(a)%float(b))+os.linesep+os.linesep  
  39.         f.write(result)  
  40.     elif '*' == operation:  
  41.         print float(a)*float(b)  
  42.         result=str(float(a)*float(b))+os.linesep+os.linesep  
  43.         f.write(result)  
  44.     f.close()  
9–15. 复制文件.  提示输入两个文件名(或者使用命令行参数). 把第一个文件的内容复制到第二个文件中去.
[python]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. import os  
  2. file1=raw_input('input first file name:')  
  3. file2=raw_input('input second file name:')  
  4.   
  5. f1=open(file1,'r')  
  6. f2=open(file2,'a+')  
  7. f2.write(os.linesep)  
  8. for line in f1:  
  9.     f2.write(line)  
  10. f1.close()  
  11. f2.close()  
9–16. 文本处理. 

人们输入的文字常常超过屏幕的最大宽度. 编写一个程序, 在一个文本文件中查找长度大于 80 个字符的文本行. 从最接近 80 个字符的单词断行, 把剩余文件插入到下一行处.程序执行完毕后, 应该没有超过 80 个字符的文本行了.

[python]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. import os  
  2.   
  3. content=[]  
  4. f=open(r'test.txt','r')  
  5. lines=f.readlines()  
  6. f.close()  
  7.   
  8. for line in lines:  
  9.     if len(line)<=80:  
  10.         content.append(line)  
  11.     else:  
  12.         words=line.strip().split()  
  13.         sum=0  
  14.         l=''  
  15.         for w in words:  
  16.             w+=' '  
  17.             sum+=len(w)  
  18.             if sum<80:  
  19.                 l+=w  
  20.             else:  
  21.                 content.append(l)  
  22.                 l=w  
  23.                 sum=len(w)  
  24.         else:  
  25.             content.append(l)  
  26.             l=''  
  27.   
  28. f=open(r'test1.txt','w')  
  29. for item in content:  
  30.     f.write(item+os.linesep)  
  31. f.close()  
9–17. 文本处理. 

创建一个原始的文本文件编辑器. 你的程序应该是菜单驱动的, 有如下这些选项:
1) 创建文件(提示输入文件名和任意行的文本输入),
2) 显示文件(把文件的内容显示到屏幕),
3) 编辑文件(提示输入要修改的行, 然后让用户进行修改),
4) 保存文件, 以及
5) 退出.

[python]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. import os  
  2.   
  3. def create(filename):  
  4.     content=[]  
  5.     while True:  
  6.         line=raw_input('pls input a line,quit as e:')  
  7.         if line != 'e':  
  8.             content.append(line)  
  9.         else:  
  10.             break  
  11.     f=open(filename,'w')  
  12.     for line in content:  
  13.         f.write(line+os.linesep)  
  14.     f.close()  
  15.   
  16. def show(filename):  
  17.     if os.path.exists(filename):  
  18.         f=open(filename)  
  19.         for line in f:  
  20.             print line,  
  21.         f.close()  
  22.     else:  
  23.         print 'no file yet'  
  24.   
  25. def edit(filename,index,content):  
  26.     f=open(filename)  
  27.     ls=f.readlines()  
  28.     f.close()  
  29.     ls[index]=content  
  30.     return ls  
  31.   
  32. def save(filename,ls):  
  33.     f=open(filename,'w')  
  34.     for line in ls:  
  35.         f.write(line)  
  36.     f.close()  
  37.   
  38. def main():  
  39.     filename=''  
  40.     ls=[]  
  41.     while True:  
  42.         print '\n'  
  43.         print '1. create a file'  
  44.         print '2. show a file'  
  45.         print '3. edit a file'  
  46.         print '4. save a file'  
  47.         print '5. quit'  
  48.   
  49.         ch=raw_input('input a choice:')  
  50.         if ch not in '1234':  
  51.             break  
  52.         elif ch=='1':  
  53.             filename=raw_input('input a file name:')  
  54.             create(filename)  
  55.         elif ch=='2':  
  56.             filename=raw_input('input a file name:')  
  57.             show(filename)  
  58.         elif ch=='3':  
  59.             if filename == '':    
  60.                 filename = raw_input('file name: ')  
  61.             index=int(raw_input('input a index of line:'))  
  62.             content=raw_input('pls input a line:')  
  63.             ls=edit(filename,index,content)  
  64.         elif ch=='4':  
  65.             save(filename,ls)  
  66.               
  67. if __name__=='__main__':  
  68.     main()  
9–18. 搜索文件.  提示输入一个字节值(0 - 255)和一个文件名. 显示该字符在文件中出现的次数.
[python]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. value=int(raw_input('input a value between 0 and 255:'))  
  2. filename=raw_input('input a fielname:')  
  3.   
  4. ch=chr(value)  
  5. f=open(filename)  
  6. print sum(iterm.count(ch) for iterm in f)  
  7. f.close()  
9–19. 创建文件. 

创建前一个问题的辅助程序. 创建一个随机字节的二进制数据文件, 但某一特定字节会在文件中出现指定的次数. 该程序接受三个参数:
1) 一个字节值( 0 - 255 ),
2) 该字符在数据文件中出现的次数, 以及
3) 数据文件的总字节长度.
你的工作就是生成这个文件, 把给定的字节随机散布在文件里, 并且要求保证给定字符在文件中只出现指定的次数, 文件应精确地达到要求的长度.

[python]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. import random  
  2. def createfile(value,count,len):  
  3.     ls=[]  
  4.     n=len-count  
  5.     for i in range(n):  
  6.         ran=random.randint(0,255)  
  7.         if ran!=value:  
  8.             ls.append(chr(ran))  
  9.         elif ran==value and value==0:  
  10.             ran=random.randint(1,255)  
  11.             ls.append(chr(ran))  
  12.         elif ran==value and value==255:  
  13.             ran=random.randint(0,254)  
  14.             ls.append(chr(ran))  
  15.         elif ran==value:  
  16.             ran=random.randint(0,value-1)  
  17.             ls.append(chr(ran))  
  18.     for i in range(count):  
  19.         ls.insert(random.randint(0,n),chr(value))  
  20.     f=open(r'test.txt','wb')  
  21.     f.write(''.join(ls))  
  22.     f.close()  
  23. createfile(97,3,50)  
  24. f=open(r'test.txt','rb')  
  25. for i in f:  
  26.     print i  
  27. f.seek(0,0)  
  28. print len(f.readlines()[0])  
  29. f.close()  
9–20. 压缩文件. 

写一小段代码, 压缩/解压缩 gzip 或 bzip 格式的文件. 可以使用命令行下的 gzip 或 bzip2 以及 GUI 程序 PowerArchiver , StuffIt , 或 WinZip 来确认你的 Python支持这两个库.

[python]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. import gzip  
  2. #compress  
  3. f_in=open(r'test.txt','rb')  
  4. f_out=gzip.open(r'test.txt.gz','wb')  
  5. f_out.writelines(f_in)  
  6. f_out.close()  
  7. f_in.close()  
  8. #decompress  
  9. f=gzip.open(r'test.txt.gz','rb')  
  10. f_out=open(r'test1.txt','wb')  
  11. content=f.read()  
  12. f_out.write(content)  
  13. f.close()  
  14. f_out.close()  
9–21. ZIP 归档文件. 

创建一个程序, 可以往 ZIP 归档文件加入文件, 或从中提取文件,有可能的话, 加入创建ZIP 归档文件的功能.

[python]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. import zipfile  
  2. def create_zipfile(zipname,filename1,filename2):  
  3.     z=zipfile.ZipFile(zipname,'w')  
  4.     z.write(filename1)  
  5.     z.write(filename2)  
  6.     z.close()  
  7.   
  8. def add_zipfile(zipname,filename):  
  9.     z=zipfile.ZipFile(zipname,'a')  
  10.     z.write(filename)  
  11.     z.close()  
  12.   
  13. def extract_zipfile(zipname,filename):  
  14.     z=zipfile.ZipFile(zipname,'r')  
  15.     z.extract(filename)  
  16.     z.close()  
  17.   
  18. if __name__=='__main__':  
  19.     create_zipfile(r'test.zip',r'test.txt',r'test1.txt')  
  20.     add_zipfile(r'test.zip',r'test2.txt')  
  21.     extract_zipfile(r'test.zip',r'test.txt')  
9–22. ZIP 归档文件. 

unzip -l 命令显示出的 ZIP 归档文件很无趣. 创建一个 Python脚本 lszip.py , 使它可以显示额外信息: 压缩文件大小, 每个文件的压缩比率(通过比较压缩前后文件大小), 以及完成的 time.ctime() 时间戳, 而不是只有日期和 HH:MM .
提示: 归档文件的 date_time 属性并不完整, 无法提供给 time.mktime() 使用....这由你自己决定.

[python]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. import zipfile,os,time  
  2.   
  3. filename=raw_input('zip file name:')  
  4. print 'zip file size: %d bytes' %(os.stat(filename).st_size)  
  5. z=zipfile.ZipFile(filename,'r')  
  6. print 'filename\tdatetime\tsize\tcompress size\trate'  
  7. for info in z.infolist():  
  8.     t = time.ctime(time.mktime(tuple(list(info.date_time) + [000])))   
  9.     print '%s\t%s\t%d\t%d\t%.2f%%' %(info.filename, t, info.file_size, info.compress_size, float(info.compress_size) / info.file_size * 100)  
  10. z.close()  
9–23. TAR 归档文件. 

为 TAR 归档文件建立类似上个问题的程序. 这两种文件的不同之处在于 ZIP 文件通常是压缩的, 而 TAR 文件不是, 只是在 gzip 和 bzip2 的支持下才能完成压缩工作. 加入任意一种压缩格式支持.附加题: 同时支持 gzip 和 bzip2 .

[python]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. import tarfile  
  2. def create_tarfile(tarname,filename1,filename2):  
  3.     t=tarfile.open(tarname,'w:gz')#w:bz2  
  4.     t.add(filename1)  
  5.     t.add(filename2)  
  6.     t.close()  
  7.   
  8. def extract_tarfile(tarname):  
  9.     t=tarfile.open(tarname,'r')  
  10.     t.extractall(r'D:\test')  
  11.     t.close()  
  12.   
  13. if __name__=='__main__':  
  14.     create_tarfile(r'test.tar.gz',r'test.txt',r'test1.txt')  
  15.     extract_tarfile(r'test.tar.gz')  
9–24. 归档文件转换. 

参考前两个问题的解决方案, 写一个程序, 在 ZIP (.zip) 和TAR/gzip (.tgz/.tar.gz) 或 TAR/bzip2 (.tbz/.tar.bz2) 归档文件间移动文件. 文件可能是已经存在的, 必要时请创建文件.

[python]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. import zipfile,tarfile,os  
  2.   
  3. def movefile(src,dst,filename):  
  4.     if src.endswith('.zip'and dst.endswith(('.tar.gz''.tgz''.tbz''.tar.bz2')):  
  5.         z=zipfile.ZipFile(src,'a')  
  6.         if filename not in z.namelist():  
  7.             f=open(filename,'w')  
  8.             f.close()  
  9.             z.write(filename)  
  10.             z.extract(filename)  
  11.         else:  
  12.             z.extract(filename)  
  13.         z.close()  
  14.         t=tarfile.open(dst,'r')  
  15.         ls=t.getnames()  
  16.         if filename not in ls:  
  17.             t.extractall()  
  18.             t.close()  
  19.             mode='w:gz' if dst.endswith(('tar.gz','tgz')) else 'w:bz2'  
  20.             t=tarfile.open(dst,mode)  
  21.             for name in ls+[filename]:  
  22.                 t.add(name)  
  23.                 os.remove(name)  
  24.             t.close()  
  25.         t.close()  
  26.     elif src.endswith(('.tar.gz''.tgz''.tbz''.tar.bz2')) and dst.endswith(('.zip')):  
  27.         t=tarfile.open(src,'r')  
  28.         if filename not in t.getnames():  
  29.             f=open(filename,'w')  
  30.             f.close()  
  31.         else:  
  32.             t.extract(filename)  
  33.         t.close()  
  34.         z=zipfile.ZipFile(dst,'a')  
  35.         if filename not in z.namelist():  
  36.             z.write(filename)  
  37.         z.close()  
  38.         os.remove(filename)  
  39.   
  40. if __name__=='__main__':  
  41.     movefile(r'test.zip',r'test.tar.gz',r'test2.txt')  
  42.     movefile(r'test.tar.gz',r'test.zip',r'test2.txt')  
9–25. 通用解压程序.

创建一个程序, 接受任意数目的归档文件以及一个目标目录做为参数.归档文件格式可以是 .zip, .tgz, .tar.gz, .gz, .bz2, .tar.bz2, .tbz 中的一种或几种. 程序会把第一个归档文件解压后放入目标目录, 把其它归档文件解压后放入以对应文件名命名的目录下(不包括扩展名). 例如输入的文件名为 header.txt.gz 和 data.tgz , 目录为 incoming ,header.txt 会被解压到 incoming 而 data.tgz 中的文件会被放入 incoming/data .

[python]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. import zipfile,tarfile,gzip,bz2,os  
  2.   
  3. def depressfile(src,dst):  
  4.     if os.path.isdir(src):  
  5.         filenames=os.listdir(src)  
  6.         if filenames[0].endswith(('.tar.gz''.tgz''.tbz''.tar.bz2')):  
  7.             t=tarfile.open(src+os.sep+filenames[0],'r')  
  8.             t.extractall(dst)  
  9.             t.close()  
  10.         elif filenames[0].endswith('.gz'):  
  11.             g=gzip.open(src+os.sep+filenames[0],'rb')  
  12.             ug=open(dst+os.sep+filenames[0][:-3],'wb')  
  13.             data=g.read()  
  14.             ug.write(data)  
  15.             ug.close()  
  16.             g.close()  
  17.         elif filenames[0].endswith('.bz2'):  
  18.             b=bz2.BZ2File(src+os.sep+filenames[0],'r')  
  19.             ub=open(dst+os.sep+filenames[0][:-4],'w')  
  20.             data=b.read()  
  21.             ub.write(data)  
  22.             ub.close()  
  23.             b.close()  
  24.         elif filenames[0].endswith('.zip'):  
  25.             z=zipfile.ZipFile(src+os.sep+filenames[0],'r')  
  26.             z.extractall(dst)  
  27.             z.close()  
  28.         filenames.remove(filenames[0])  
  29.         for name in filenames:  
  30.             dirname = os.path.splitext(os.path.basename(name))[0]  
  31.             if dirname in os.listdir(dst):  
  32.                 dirname = dst+os.sep+dirname+str(filenames.index(name))  
  33.             else:  
  34.                 dirname = dst+os.sep+dirname  
  35.             os.mkdir(dirname)  
  36.             if name.endswith(('.tar.gz''.tgz''.tbz''.tar.bz2')):  
  37.                 t=tarfile.open(src+os.sep+name,'r')  
  38.                 t.extractall(dirname)  
  39.                 t.close()  
  40.             elif name.endswith('.gz'):  
  41.                 g=gzip.open(src+os.sep+name,'rb')  
  42.                 ug=open(dirname+os.sep+name[:-3],'wb')  
  43.                 data=g.read()  
  44.                 ug.write(data)  
  45.                 ug.close()  
  46.                 g.close()  
  47.             elif name.endswith('.bz2'):  
  48.                 b=bz2.BZ2File(src+os.sep+name,'r')  
  49.                 ub=open(dirname+os.sep+name[:-4],'w')  
  50.                 data=b.read()  
  51.                 ub.write(data)  
  52.                 ub.close()  
  53.                 b.close()  
  54.             elif name.endswith('.zip'):  
  55.                 z=zipfile.ZipFile(src+os.sep+name,'r')  
  56.                 z.extractall(dirname)  
  57.                 z.close()  
  58.     else:  
  59.         print '%s is not a directory,input again' %(src)  
  60.   
  61. if __name__=='__main__':  
  62.     depressfile(r'D:\1',r'D:\2')  

猜你喜欢

转载自blog.csdn.net/qq_20113327/article/details/61202711
今日推荐