• 如何优雅的使用 Python 实现文件递归遍历


    今天有个脚本需要遍历获取某指定文件夹下面的所有文件,我记得很早前也实现过文件遍历和目录遍历的功能,于是找来看一看,嘿,不看不知道,看了吓一跳,原来之前我竟然用了这么搓的实现。

    先发出来看看:

    def getallfiles(dir):
    """遍历获取指定文件夹下面所有文件"""   
        if os.path.isdir(dir):
            filelist = os.listdir(dir)
            for ret in filelist:
                filename = dir + "\" + ret
                if os.path.isfile(filename):
                    print filename
                    
    def getalldirfiles(dir, basedir):
    """遍历获取所有子文件夹下面所有文件"""   
        if os.path.isdir(dir):
      muiop[]
    sdrtyuiop[]
          getallfiles(dir)
            dirlist = os.listdir(dir)
            for dirret in dirlist:
                fullname = dir + "\" + dirret
                if os.path.isdir(fullname):
                    getalldirfiles(fullname, basedir)

    我是用了 2 个函数,并且每个函数都用了一次 listdir,只是一次用来过滤文件,一次用来过滤文件夹,如果只是从功能实现上看,一点问题没有,但是这…太不优雅了吧。

    开始着手优化,方案一:

    def getallfiles(dir):
    """使用listdir循环遍历"""   
        if not os.path.isdir(dir):
            print dir
            return   
        dirlist = os.listdir(dir)
        for dirret in dirlist:
            fullname = dir + "\" + dirret
            if os.path.isdir(fullname):
                getallfiles(fullname)
            else:
                print fullname

    从上图可以看到,我把两个函数合并成了一个,只调用了一次 listdir,把文件和文件夹用 ifelse 进行了分支处理,当然,自我调用的循环还是存在。

    有木有更好的方式呢?网上一搜一大把,原来有一个现成的 os.walk() 函数可以用来处理文件(夹)的遍历,这样优化下就更简单了。

    方案二:

    def getallfilesofwalk(dir):
    """使用listdir循环遍历"""   
        if not os.path.isdir(dir):
            print dir
            return   
        dirlist = os.walk(dir)
        for root, dirs, files in dirlist:
            for file in files:
                print os.path.join(root, file)

    只是从代码实现上看,方案二是最优雅简洁的了,但是再翻看 os.walk() 实现的源码就会发现,其实它内部还是调用的 listdir 完成具体的功能实现,只是它对输出结果做了下额外的处理而已。

    附上os.walk()的源码:

    from os.path import join, isdir, islink
    
    # We may not have read permission for top, in which case we can't
    # get a list of the files the directory contains.  os.path.walk
    # always suppressed the exception then, rather than blow up for a
    # minor reason when (say) a thousand readable directories are still
    # left to visit.  That logic is copied here.
    
    try:
        # Note that listdir and error are globals in this module due   
        # to earlier import-*.   
        names = listdir(top)
    except error, err:
        if onerror is not None:
           onerror(err)
        return
        
    dirs, nondirs = [], []
    for name in names:
        if isdir(join(top, name)):
            dirs.append(name)
        else:
            nondirs.append(name)
            
    if topdown:
        yield top, dirs, nondirs
    for name in dirs:
        path = join(top, name)
        if followlinks or not islink(path):
            for x in walk(path, topdown, onerror, followlinks):
                yield x
    if not topdown:
        yield top, dirs, nondirs

    至于 listdir 和 walk 在输出时的不同点,主要就是listdir 默认是按照文件和文件夹存放的字母顺序进行输出,而 walk 则是先输出顶级文件夹,然后是顶级文件,再输出第二级文件夹,以及第二级文件,以此类推,具体大家可以把上面脚本拷贝后自行验证。

    结语:

    跟大家推荐一个学习资料分享群:706315665,里面大牛已经为我们整理好了许多的学习资料,有自动化,接口,性能等等的学习资料!人生是一个逆水行舟的过程,不进则退,咱们一起加油吧!

  • 相关阅读:
    unordered_map(hash_map)和map的比较
    软工实践第三次作业-结对项目2
    福大软工1816 · 第四次作业
    学习进度条
    软工实践第三次作业-结对项目1
    软工实践-个人项目
    hightopo学习之旅一 -- 节点动画
    vue中动态样式不起作用? scoped了解一下
    Error: Cannot find module 'webpack/schemas/WebpackOptions.json' 问题解决
    - configuration.module has an unknown property 'loader' 问题解决
  • 原文地址:https://www.cnblogs.com/gupao123/p/10102581.html
Copyright © 2020-2023  润新知