Discuss / Python / 建议使用os.walk代替os.listdir()----示例

建议使用os.walk代替os.listdir()----示例

Topic source

ywjco_567

#1 Created at ... [Delete] [Delete and Lock User]

os.walk不需要自己写递归,就能遍历指定路径的目录树。

一些来自官方文的片段:

os.walk(top, topdown=True, onerror=None, followlinks=False)

通过自上而下或自下而上的方法遍历目录树,生成文件名。对于以top为根目录(包括top本身)的树中的每个目录,它生成3-元组(dirpath, dirnames, filenames)。
注:3-元组分别是(当前目录列表),(子目录列表),(文件列表)。

要获取到dirpath中的文件或目录的完整路径(从顶部开始),请执行os.path.join(dirpath、name)。

在 3.5 版更改:此函数现在调用os.scandir()而不是os.listdir(),通过减少对os.stat()的调用次数来加快速度。默认情况下,将忽略来自scandir()调用的错误。

使用scandir()而不是listdir()可以显著提高还需要文件类型或文件属性信息的代码性能。

有兴趣自己到官网看看:

https://docs.python.org/zh-cn/3/library/os.html?highlight=os#os.walk

其它:遍历时尽量用生成器来输出,而不是用列表,以减少系统资源占用。

直接上例:

# !/usr/bin/python3
# -*-coding:UTF-8-*-
# FileName: search_file.py

import os

def search_file(dir, filetype):
    '''
        查找指定目录及文件类型的文件,不输入文件类型退出。
        os.walk函数在3.5版改为调用os.scandir()实现,默认情况下,将忽略来自scandir()调用的错误。
        但可以通过指定可选参数onerror来报告错误
    '''
    path_file = ''
    if path == None or path == '.':
        path = os.getcwd()
    if filetype =='': return 0
    try:
        for root, dirs, files in os.walk(dir, topdown=True, onerror=OSError(FileNotFoundError)):
            # onerror=OSError(FileNotFoundError):当所请求的文件或目录不存在时将被引发
            for name in files:
                if os.path.splitext(name)[1]== '.' + filetype:
                    path_file = os.path.join(root, name)
                    yield path_file
    except Exception as e:
        print(f'输入目录参数dir是: “{dir}”, 输入文件类型参数filetype是: “{filetype}”')
        print(f'输入错误:“{e.__context__}”,请核对后再次运行程序。')

def main():
    _dir = str(input("请输入要查找文件的路径,如果直接回车则查找当前路径:"))
    _ext = str(input("请输入要查找文件的类型(例如‘txt’),如果直接回车退出:"))
    for s in search_file(_dir, _ext):
        print(s)

if __name__ == '__main__':
    main()

ywjco_567

#2 Created at ... [Delete] [Delete and Lock User]

这段写错:

if path == None or path == '.':
    path = os.getcwd()

改为:

if dir == None or dir == '.':
    dir = os.getcwd()

一盒噪噪

#3 Created at ... [Delete] [Delete and Lock User]

感谢!!

一盒噪噪

#4 Created at ... [Delete] [Delete and Lock User]

os.walk函数本质上是一个生成器

基本原理就是@何以不将就_写的那块代码

import os
def findstr(p,str):
    for x in os.listdir(p):
        path = os.path.join(p,x)
        if os.path.isfile(path) and str in x :
            print( path)
        if os.path.isdir(path):
            findstr(path,str)

每次迭代都返回三个值:

①当前路径

②当前路径中子路径(文件夹)

③当前路径中的文件(除文件夹外)

我猜测walk源码大概是一个递归函数 

返回值功能类似于: 

for dirname in dirnames: 

    return dirpath filenames walk(dirname)

其中会给三个元组分类储存

用walk函数省略了给路径分类的步骤

直接筛选出了filenames,再逐个生成,判断其中是否含有指定字符串就可以啦

很棒,感谢答主


  • 1

Reply