Linux下海量文件指定创建时段筛选的Python代码优化问询
提升大目录文件时段筛选速度的优化方案
我来分享几个能显著提升你这段代码运行速度的方法,尤其是在处理数千个文件的大目录时:
1. 用os.scandir替代os.listdir+os.path.getctime(性能提升核心)
这是最有效的优化点!os.listdir只会返回文件名,之后你需要对每个文件单独调用os.path.getctime获取时间——这意味着每个文件都要发起一次系统调用,文件越多,开销越大。
而os.scandir(Python 3.5+支持)会一次性获取目录下所有文件的元数据(包括时间信息),利用了系统底层的getdents调用,大幅减少系统调用次数,速度能提升数倍。它返回的DirEntry对象可以直接通过stat()获取文件时间,无需额外调用。
2. 提前转换时间范围为时间戳,避免重复类型转换
原代码中每次都把文件时间戳转成datetime对象再和date_start/date_end比较,这会产生额外的类型转换开销。我们可以先把date_start和date_end转成时间戳,直接和文件的时间戳比较,跳过datetime转换步骤。
3. 消除冗余的目录遍历
你的代码里先执行了files = os.listdir(ARCHIVE_FOLDER),之后又循环os.listdir(ARCHIVE_FOLDER)——这是完全冗余的,直接遍历一次即可,避免重复读取目录内容。
优化后的完整代码
from datetime import datetime, timedelta import os def get_time(): tmp_date = datetime.now() year = tmp_date.year month = tmp_date.month day = tmp_date.day date_start = datetime(year, month, day, 7,30) date_end = datetime(year, month, day, 19,30) shift = "Day Shift" if date_start < tmp_date < date_end: # 当前是白班时段,筛选白班文件 pass else: # 当前是夜班时段,筛选夜班文件(跨天) if tmp_date < date_start: # 当前在凌晨7:30前,筛选前一天19:30到当天7:30的文件 date_start = datetime(year, month, day, 19,30) - timedelta(1) date_end = datetime(year, month, day, 7,30) else: # 当前在19:30后,筛选当天19:30到次日7:30的文件 date_start = datetime(year, month, day, 19,30) date_end = datetime(year, month, day, 7,30) + timedelta(1) shift = "Night Shift" # 转换为时间戳,方便后续比较 return date_start.timestamp(), date_end.timestamp(), shift def get_qc_success(ROOT_FOLDER): start_ts, end_ts, shift = get_time() files = [] ARCHIVE_FOLDER = os.path.join(ROOT_FOLDER,"LOMS","ARCHIVE") # 使用os.scandir遍历目录,一次性获取元数据 with os.scandir(ARCHIVE_FOLDER) as entries: for entry in entries: # 只处理文件,跳过目录 if entry.is_file(): # 获取文件状态改变时间戳(Linux下st_ctime是状态改变时间,若需创建时间可尝试st_birthtime) file_ctime_ts = entry.stat().st_ctime if start_ts < file_ctime_ts < end_ts: files.append(entry.name) len_success = len(files) return files, len_success, shift
额外说明
- 关于Linux下的文件创建时间:Linux默认的
st_ctime是文件状态改变时间(比如权限修改、内容修改都会更新),如果你的需求是严格的文件创建时间,可以尝试entry.stat().st_birthtime,但这个字段依赖文件系统支持(比如ext4支持,部分老文件系统不支持)。 - 内存优化:
os.scandir返回的是迭代器,不会一次性把所有文件信息加载到内存,即使目录有几万个文件,内存占用也很低。
内容的提问来源于stack exchange,提问作者Royal




