Python遍历读取文件或文件夹的两种方法及实现

远山来客
远山来客
发布时间:2026-10-15| 4人浏览过
原创

本文详解Python中遍历读取目录的两种常用方法:os.listdir与os.walk。os.listdir仅获取当前层级文件列表,而os.walk可递归遍历所有子目录。文章通过具体代码示例对比两者返回值差异,并提供了支持多后缀过滤、递归/非递归选项的完整封装函数,帮助开发者高效处理机器学习或深度学习中的文件读取需求。

在进行机器学习或深度学习算法开发时,经常需要遍历特定目录以读取文件,尤其是针对具有特定后缀的文件,例如图像文件可能需要读取jpg、png或bmp格式。由于Python标准库函数缺乏这种高度定制化的功能,因此需要对现有功能进行封装和扩展。

示例说明

假设存在如下目录结构,其中以.bmp结尾的为文件,其余为文件夹。后续所有程序示例均基于该目录结构进行演示。

os.listdir方法

os.listdir函数仅读取当前指定路径下的文件和文件夹,并返回一个列表。以下是读取demo目录结构的代码及运行结果:

path = r'D:\data'
items = os.listdir(path)  # ==> ['1.bmp', '2.bmp', 'a', 'b']

os.walk方法

os.walk函数本身已具备遍历读取功能,能够包含所有子文件(夹),但其返回结果并非像os.listdir那样直接返回list,而是一个较为复杂的数据结构,难以直接使用,因此通常需要进行额外处理。我们可以通过for语句将其打印出来观察:

path = r'D:\data'
# part 1
for items in os.walk(path):
    print(items)
# part 2
for main_dir, sub_dir_list, sub_file_list in os.walk(path):
    print(main_dir, sub_dir_list, sub_file_list)

运行结果如下:

# part 1 ('D:\\data', ['a', 'b'], ['1.bmp', '2.bmp']) ('D:\\data\\a', [], ['a1.bmp']) ('D:\\data\\b', [], ['b1.bmp']) # part 2 D:\data ['a', 'b'] ['1.bmp', '2.bmp'] D:\data\a [] ['a1.bmp'] D:\data\b [] ['b1.bmp']

通过迭代器输出os.walk()的结果,可以发现每一条记录包含三个部分(part 1)。在part 2中,我们将这三个部分分别命名为main_dir、sub_dir_list和sub_file_list,下面对其进行简要解释:

  • main_dir:遍历过程中得到的当前路径下所有文件夹的根目录
  • sub_dir_list:main_dir直接包含的子文件夹列表
  • sub_file_list:main_dir直接包含的文件列表

将main_dir与sub_file_list中的文件名拼接,即可得到该路径下的所有完整文件路径。

在此场景下,sub_dir_list并无额外用途,因为子文件夹的内容已经包含在main_dir的遍历结果中,无需再单独遍历sub_dir_list。

遍历读取代码实现

代码逻辑设计如下:

需具备后缀识别功能,且支持同时识别多种后缀

需支持递归和非递归两种遍历模式

返回的路径以入参path为前缀,因此如果path是完整路径,则返回完整路径;否则返回相对路径

# -*- coding: utf-8 -*-
import os


def file_ext(filename, level=1):
    """
    return extension of filename

    Parameters:
    -----------
    filename: str
        name of file, path can be included
    level: int
        level of extension.
        for example, if filename is 'sky.png.bak', the 1st level extension
        is 'bak', and the 2nd level extension is 'png'

    Returns:
    --------
    extension of filename
    """
    return filename.split('.')[-level]


def _contain_file(path, extensions):
    """
    check whether path contains any file whose extension is in extensions list

    Parameters:
    -----------
    path: str
        path to be checked
    extensions: str or list/tuple of str
        extension or extensions list

    Returns:
    --------
    return True if contains, else return False
    """
    assert os.path.exists(path), 'path must exist'
    assert os.path.isdir(path), 'path must be dir'

    if isinstance(extensions, str):
        extensions = [extensions]

    for file in os.listdir(path):
        if os.path.isfile(os.path.join(path, file)):
            if (extensions is None) or (file_ext(file) in extensions):
                return True
    return False


def _process_extensions(extensions=None):
    """
    preprocess and check extensions, if extensions is str, convert it to list.

    Parameters:
    -----------
    extensions: str or list/tuple of str
        file extensions

    Returns:
    --------
    extensions: list/tuple of str
        file extensions
    """
    if extensions is not None:
        if isinstance(extensions, str):
            extensions = [extensions]
        assert isinstance(extensions, (list, tuple)), \
            'extensions must be str or list/tuple of str'
        for ext in extensions:
            assert isinstance(ext, str), 'extension must be str'
    return extensions


def get_files(path, extensions=None, is_recursive=True):
    """
    read files in path. if extensions is None, read all files, if extensions
    are specified, only read the files who have one of the extensions. if
    is_recursive is True, recursively read all files, if is_recursive is False,
    only read files in current path.

    Parameters:
    -----------
    path: str
        path to be read
    extensions: str or list/tuple of str
        file extensions
    is_recursive: bool
        whether read files recursively. read recursively is True, while just
        read files in current path if False

    Returns:
    --------
    files: the obtained files in path
    """
    extensions = _process_extensions(extensions)
    files = []
    # get files in current path
    if not is_recursive:
        for name in os.listdir(path):
            fullname = os.path.join(path, name)
            if os.path.isfile(fullname):
                if (extensions is None) or (file_ext(fullname) in extensions):
                    files.append(fullname)
        return files
    # get files recursively
    for main_dir, _, sub_file_list in os.walk(path):
        for filename in sub_file_list:
            fullname = os.path.join(main_dir, filename)
            if (extensions is None) or (file_ext(fullname) in extensions):
                files.append(fullname)
    return files


def get_folders(path, extensions=None, is_recursive=True):
    """
    read folders in path. if extensions is None, read all folders, if
    extensions are specified, only read the folders who contain any files that
    have one of the extensions. if is_recursive is True, recursively read all
    folders, if is_recursive is False, only read folders in current path.

    Parameters:
    -----------
    path: str
        path to be read
    extensions: str or list/tuple of str
        file extensions
    is_recursive: bool
        whether read folders recursively. read recursively is True, while just
        read folders in current path if False

    Returns:
    --------
    folders: the obtained folders in path
    """
    extensions = _process_extensions(extensions)
    folders = []
    # get folders in current path
    if not is_recursive:
        for name in os.listdir(path):
            fullname = os.path.join(path, name)
            if os.path.isdir(fullname):
                if (extensions is None) or \
                        (_contain_file(fullname, extensions)):
                    folders.append(fullname)
        return folders
    # get folders recursively
    for main_dir, _, _ in os.walk(path):
        if (extensions is None) or (_contain_file(main_dir, extensions)):
            folders.append(main_dir)
    return folders


if __name__ == '__main__':
    path = r'.\data'

    files = get_files(path)
    print(files)  # ==> ['D:\\data\\1.bmp', 'D:\\data\\2.bmp', 'D:\\data\\a\\a1.bmp', 'D:\\data\\b\\b1.bmp']

    folders = get_folders(path)
    print(folders)  # ==> ['D:\\data', 'D:\\data\\a', 'D:\\data\\b']

以上为Python实现遍历读取文件或文件夹的详细内容,更多关于Python遍历读取文件的资料请关注本站其它相关文章!

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。