You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python中os.scandir多次迭代后create_dir_by_keyword函数失效排查

问题原因分析

核心问题是os.scandir()返回的是一次性迭代器。迭代器的特性是只能被遍历一次,遍历完成后就会耗尽,后续再遍历不会产生任何元素。

你在全局作用域中提前执行了scanned_dir_keyword_files = os.scandir(dir_keyword_files),然后:

  1. read_keywords()函数中已经遍历了这个迭代器,把所有元素都取完了;
  2. 当create_dir_by_keyword()再尝试遍历同一个迭代器时,已经没有元素可以迭代,所以循环体完全不执行,自然不会创建文件夹。

同样的问题也出现在scan_dir_source_files()两次调用的情况:第一次调用遍历了迭代器,第二次调用就没有输出,和你运行结果里的情况一致。


解决方案

有两种常见的修复方式:

方式1:每次需要遍历的时候重新生成扫描结果

不要在全局作用域提前保存迭代器,而是在每个需要的函数内部调用os.scandir(),这样每次函数执行都会获取新的迭代器:

import os

dir_source_files = 'source files'
dir_destination = 'destination'
dir_keyword_files = 'keywords'

def scan_dir_source_files():
    # 函数内部重新扫描,用with自动关闭资源
    with os.scandir(dir_source_files) as scanned_files:
        for file in scanned_files:
            print(file)
    print("scan_dir_source_files() function called\n")

def read_keywords():
    with os.scandir(dir_keyword_files) as scanned_files:
        for file in scanned_files:
            # 使用with语句自动关闭文件,避免资源泄漏
            with open(file.path, 'r', encoding='utf-8') as f:
                print(f"keyword found: {f.read()}")
    print("read_keywords() function called\n")

def create_dir_by_keyword():
    with os.scandir(dir_keyword_files) as scanned_files:
        for file in scanned_files:
            print(f"\nfile found in dir_keyword_files:\n{file} name of new folder: {os.path.splitext(file.name)[0]}")
            new_dir_name = os.path.splitext(file.name)[0]
            path_for_new_dir = os.path.join(dir_destination, new_dir_name)
            try:
                os.makedirs(path_for_new_dir, exist_ok=False)
                print(f"directory creation successful. created directory:\n{new_dir_name}")
            except OSError as error:
                print(f"directory creation not successful. '{new_dir_name}' already exists")
    print("create_dir_by_keyword() function called\n")

scan_dir_source_files()
scan_dir_source_files()
read_keywords()
create_dir_by_keyword()

方式2:将扫描结果转为列表保存(适合文件数量不多的场景)

如果目录下文件数量不多,可以一次性把扫描结果转成列表,这样列表可以被多次遍历:

import os

dir_source_files = 'source files'
dir_destination = 'destination'
dir_keyword_files = 'keywords'

# 转成列表,可多次遍历
scanned_dir_source_files = list(os.scandir(dir_source_files))
scanned_dir_keyword_files = list(os.scandir(dir_keyword_files))
scanned_dir_destination = list(os.scandir(dir_destination))

def scan_dir_source_files():
    for file in scanned_dir_source_files:
        print(file)
    print("scan_dir_source_files() function called\n")

def read_keywords():
    for file in scanned_dir_keyword_files:
        with open(file.path, 'r', encoding='utf-8') as f:
            print(f"keyword found: {f.read()}")
    print("read_keywords() function called\n")

def create_dir_by_keyword():
    for file in scanned_dir_keyword_files:
        print(f"\nfile found in dir_keyword_files:\n{file} name of new folder: {os.path.splitext(file.name)[0]}")
        new_dir_name = os.path.splitext(file.name)[0]
        path_for_new_dir = os.path.join(dir_destination, new_dir_name)
        try:
            os.makedirs(path_for_new_dir, exist_ok=False)
            print(f"directory creation successful. created directory:\n{new_dir_name}")
        except OSError as error:
            print(f"directory creation not successful. '{new_dir_name}' already exists")
    print("create_dir_by_keyword() function called\n")

scan_dir_source_files()
scan_dir_source_files()
read_keywords()
create_dir_by_keyword()

代码可读性优化建议
  1. 避免全局变量依赖:全局变量会让函数的行为依赖外部状态,降低可维护性。建议把目录路径作为参数传递给函数,或者在函数内部定义(如果是固定路径)。
  2. 用with语句管理资源:无论是os.scandir()还是打开文件,with语句可以自动关闭资源,避免泄漏,代码更安全简洁。
  3. 函数职责单一化:比如read_keywords()可以返回关键词列表而非直接打印,create_dir_by_keyword()专注于创建目录,这样函数更灵活、可复用性更高。
  4. 命名更直观:比如把dir_source_files改成SOURCE_DIR(常量大写),scan_dir_source_files改成print_source_files,更清晰体现函数功能。
  5. 指定文件编码:打开文件时添加encoding='utf-8',避免出现hörbuch这类乱码问题。
  6. 注释聚焦逻辑意图:注释不用重复代码做了什么,而是解释为什么这么做,比如标注迭代器的特性,或者函数的核心设计目的。

内容的提问来源于stack exchange,提问作者fbn001

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 14:30:51