zoukankan      html  css  js  c++  java
  • python编程快速上手之第9章实践项目参考答案

    本章介介绍了shutil,zipfile模块的使用,我们先来认识一下这2个模块吧。

    一.shutil模块

    shutil模块主要用于对文件或文件夹进行处理,包括:复制,移动,改名和删除文件,在shutil模块中主要以下这么几个函数:

    1.复制文件和文件夹

    shutil模块提供了2个函数:shutil.copy()和shutil.copytree()

    shutil.copy的语法格式:

    copy(src, dst)

    作用:

    将src处的文件复制到dst路径中去,其中src,dst都是字符串形式的路径。如果dst是一个文件名,它将作为被复制文件的新名字,相当于把原路径的文件复制到新路径并改名。

    举例:

    将/etc/my.cnf 复制到/root/mysql中

    In [12]: import shutil
    
    In [13]: shutil.copy('/etc/my.cnf','/root/mysql/')
    Out[13]: '/root/mysql/my.cnf'
    
    In [15]: ll /root/mysql/
    total 4
    -rw-r--r--. 1 root 960 Apr 22 16:57 my.cnf

    将/etc/my.cnf复制到/root/mysql并改名为mysql.cnf

    In [16]: shutil.copy('/etc/my.cnf','/root/mysql/mysql.cnf')
    Out[16]: '/root/mysql/mysql.cnf'
    
    In [17]: ll /root/mysql/
    total 8
    -rw-r--r--. 1 root 960 Apr 22 16:57 my.cnf
    -rw-r--r--. 1 root 960 Apr 22 17:00 mysql.cnf

    shutil.copytree的语法格式:

    copytree(src, dst)

    作用:

    复制整个文件夹。将src处的文件夹,包括它的所有文件和子文件夹,复制到路径dst处的文件夹。返回一个新复制的文件夹路径的字符串。

    举例:

    In [20]: shutil.copytree('/etc/yum.repos.d','/root/repo.back')
    Out[20]: '/root/repo.back'
    
    In [21]: ll /root/drwxr-xr-x. 2 root 4096 Apr 23  2017 repo.back/
    drwxr-xr-x. 2 root 4096 Apr 23  2017 repo.bak/

    注意:dst必须是一个系统中不存在目录,不然会报错:

    In [20]: shutil.copytree('/etc/yum.repos.d','/root/repo.bak')
    FileExistsError: [Errno 17] File exists: '/root/repo.bak'

    2.文件和文件夹的移动和改名

    shutil.move()

    语法格式:

    move(stc,dst)

    作用:

    将路径stc处的文件夹移动到路径dst,并返回新位置的绝对路径的字符串。

    举例:

    将/root/目录下的a.txt移动到/root/test/目录中

    In [26]: shutil.move('/root/a.txt','/root/test/')
    Out[26]: '/root/test/a.txt'
    
    In [27]: ll /root/test
    total 4
    -rw-r--r--. 1 root 6 Apr 22 17:30 a.txt

    注意:

    如果dst指向一个文件夹,src文件将移动到dst中,并保持原来的文件名,前提是dst必须是系统中已经存在的目录。

    如果目标文件中已存在相同名称的文件将被覆盖,需要注意。

    3.删除文件和文件夹

    在os模块中:

    os.remove(path)可以删除一个文件

    os.rmdir(path)可以删除一个空文件夹。

    在shutil模块中:

    shutil.rmtree(path)可以删除一个文件夹及其所有的内容。

    语法格式:

    os.rmdir(path)
    shutil.rmtree(path)

    举例:

     1 In [34]: os.remove('/root/test/a.txt')
     2 
     3 In [35]: ll /root/test/
     4 total 0
     5 
     6 In [36]: shutil.move('/root/CentOS-Base.repo','/root/test/')
     7 Out[36]: '/root/test/CentOS-Base.repo'
     8 
     9 In [37]: ll test
    10 total 4
    11 -rw-r--r--. 1 root 2573 Apr 23  2017 CentOS-Base.repo
    12 
    13 In [38]: shutil.rmtree('/root/test')
    14 
    15 In [39]: ll
    16 total 12
    17 -rw-------. 1 root 1468 Apr 16 21:03 anaconda-ks.cfg
    18 drwxr-xr-x. 2 root   57 Apr 23  2017 download/
    19 drwxr-xr-x. 2 root   37 Apr 22 17:00 mysql/
    20 drwxr-xr-x. 6 root   95 Apr 16 21:58 py34/
    21 drwxr-xr-x. 3 root   18 Apr 16 23:01 python/
    22 drwxr-xr-x. 2 root 4096 Apr 23  2017 repo.back/
    23 drwxr-xr-x. 2 root 4096 Apr 23  2017 repo.bak/

    注意:

    以上的删除都是永久的删除。为了安全起见最好使用send2trash第三方模块,它会将删除的文件放入回收站。在python3中已集成了这个模块。

    send2trash用法:

    import send2trash
    send2trash(path)

    二.遍历目录树

    对文件的处理,尤其是批量操作就不得不对目录进行遍历。在python中os模块中的os.walk()函数就可以做到。

    这个函数会递归遍历指定目录及子目录,返回一个3元组信息:当前目录名,子目录名,文件名,不包括 . 和 ..

    常见用法:

    #!/usr/bin/env python3.4
    #coding:utf-8
    import os
    for foldName,subfolders,filenames in os.walk('/root/'):
        print('The current folder is: ' + foldName)
        for subfolder in subfolders:
            print('subfolder of ' + foldName + ':' + subfolder)
        for filename in filenames:
            print('file inside ' + foldName + ':' + filename)
        print('')

    三.实践项目参考答案

     1 #!/usr/bin/env python3.4
     2 # coding:utf-8
     3 import os
     4 import shutil
     5 import send2trash
     6 
     7 # 9.8.1
     8 # 拷贝指定格式文件到指定目录,下面程序是将/etc目录下所的.conf文件拷贝到/root/test/目录里。
     9 src = '/etc/'
    10 dst = '/root/test/'
    11 ftype = '.conf'
    12 count = 0
    13 for filename in os.listdir(src):
    14     if filename.endswith(ftype):
    15         shutil.copy(src + filename,dst)
    16         count += 1
    17         print('文件 ' + src + filename + '	被拷贝到---> ' + dst + ' 目录下')
    18 print("该目录下所有的 " + ftype + "文件已被拷贝到" + dst + "目录下")
    19 print('共拷贝了 ' + str(count) + ' 个文件')
    20 
    21 # 9.8.2
    22 # 搜索指定目录下大于100M的文件,打印出来并删除
    23 # 可以手动创建一个指定大小的空文件做试验
    24 # dd if=/dev/zero of=hello.txt bs=100M count=1
    25 for foldname,subfolders,filenames in os.walk(dst):
    26     for files in filenames:
    27         if os.path.getsize(dst + files) / 1024 /1024 > 100:
    28             print('大于100M的文件有:' + files + ' ' +  str(os.path.getsize(dst + files) / 1024 / 1024) +'Mb')
    29             send2trash.send2trash(dst + files)

     9.8.3

    假设test文件夹下有如下文件,文件是以spam开头加上数字编号,但是编号并不连续有缺失,而且有的并不包含数字,我们需要找出不符合文件名的文件并重新命名成连续编号的文件名。

    (py34) [root@master test]# ls
    spam002.txt  spam004.txt  spam006.txt  spam008.txt  spam999.txt
    spam003.txt  spam005.txt  spam007.txt  spam011.txt  spamkkdf.txt

    参考代码如下:

     1 #!/usr/bin/env python3.4
     2 # coding:utf-8
     3 import re
     4 import os
     5 fdir = '/root/python/py-9/test/'
     6 fdir_list = os.listdir(fdir)
     7 fdir_count = len(fdir_list)
     8 print(fdir_list)
     9 print('该目录下共有 %d 个文件' %fdir_count)
    10 f_pre = 'spam'
    11 f_num = []
    12 f_end = '.txt'
    13 fs_list = []
    14 # 这里只假定文件数量小100的情况
    15 for i in range(1,fdir_count + 1):
    16     if i < 10:
    17         f_name = f_pre + '00' + str(i) + f_end
    18         f_num.append('00' + str(i))
    19         fs_list.append(f_name)
    20     else:
    21         f_name = f_pre + '0' + str(i) + f_end
    22         f_num.append('0' + str(i))
    23         fs_list.append(f_name)
    24 max_f_num = max(f_num)
    25 print('该目录下文件最大的编号应该是: %s' %max_f_num)
    26 print('正确的文件名应该是:')
    27 print(fs_list)
    28 
    29 # 使用正则表达式搜索目录中已有编号的文件并存入列表yf_num中
    30 re_num = 'd{3}'
    31 yf_num = re.findall(f_pre + re_num + f_end,' '.join(fdir_list))
    32 ra_num = re.findall(re_num,' '.join(fdir_list))
    33 print('目录中已有编号文件:
    %s' %yf_num)
    34 
    35 # fq_list为目录中缺失编号的文件名列表
    36 # fx_list为当前目录中需要修改名称的文件列表
    37 fq_list = []
    38 fx_list = []
    39 # 定位缺失的编号文件并放入列表中
    40 for a in fs_list:
    41     if a not in yf_num:
    42         fq_list.append(a)
    43 print('缺少的文件编号是:
    %s' %fq_list)
    44 
    45 # 查找目录中没有编号或不正连续的编号文件并放入列表中
    46 for f_rename in fdir_list:
    47     if f_rename not in fs_list: 
    48         fx_list.append(f_rename)
    49 print('需要修改的文件名有:
    %s' %fx_list)
    50 
    51 # 更改文件名
    52 for k in fq_list:
    53     for v in fx_list:
    54         os.rename(fdir + v,fdir + k)
    55         # 每当修完一个文件名应该更新一下这个列表
    56         fx_list.remove(v)
    57 print('改完名后的结果为:')
    58 os.system('ls')

    今天回来看看,决定用函数的方式来练习并实现,代码有了一些小的改进,上代码:

     1 #!/usr/bin/env python3.4
     2 # coding:utf-8
     3 import re
     4 import os
     5 fdir = '/root/github/shell/python3/py-9/test/'
     6 fdir_list = os.listdir(fdir)
     7 fdir_f_count = len(fdir_list)
     8 print('当前目录的文件为:
    %s' % fdir_list)
     9 def getFileformat(f_pre,f_num,f_end):
    10     fileformat = f_pre + f_num + f_end
    11     return fileformat
    12 file_list = []
    13 def getTruefile():
    14     for i in range(1,fdir_f_count + 1):
    15         if i < 10:
    16             f_format = getFileformat('spam','00' + str(i),'.txt')
    17             file_list.append(f_format)
    18         else:
    19             f_format = getFileformat('spam','0' + str(i),'.txt')
    20             file_list.append(f_format)
    21     return file_list
    22 truefilelist = getTruefile()
    23 print('正确的文件编号应该是:
    %s' %truefilelist)
    24 lostnumfilelist = []
    25 def getLostnumfile(fdirlist,truelist):
    26     for lf in truelist:
    27         if lf not in fdirlist:
    28             lostnumfilelist.append(lf)
    29     return lostnumfilelist
    30 lostnumfile = getLostnumfile(fdir_list,file_list)
    31 print('缺失的文件编号为:
    %s' %lostnumfile)
    32 
    33 renamelist = []
    34 def getrenamefile(fdirlist,func):
    35     for a in fdirlist:
    36         if a not in func:
    37             renamelist.append(a)
    38     return renamelist
    39 renamefilelist = getrenamefile(fdir_list,file_list)
    40 print('需要修改的文件是
    %s' %renamefilelist)
    41 
    42 def renamefile(func1,func2):
    43     for b in func1:
    44         for c in func2:
    45             os.rename(fdir + c,fdir + b)
    46             func2.remove(c)
    47 rename = renamefile(lostnumfile,renamefilelist)
    48 os.chdir(fdir)
    49 print('修改后的结果为:')
    50 os.system('ls')
  • 相关阅读:
    Silverlight数据绑定之DataGrid
    演练:使用属性自定义 DataGrid 控件
    [开源下载] 【开源项目】EasySL for Silverlight 4
    Expression Blend实例中文教程(13)
    Expression Blend实例中文教程(12)
    Expression Blend实例中文教程(11)
    Expression Blend实例中文教程(10)
    Expression Blend实例中文教程(8)
    Expression Blend实例中文教程(7)
    Expression Blend实例中文教程(6)
  • 原文地址:https://www.cnblogs.com/mfyang/p/6749609.html
Copyright © 2011-2022 走看看