如何使用PyArrow递归列出HDFS中的子文件夹与文件
递归遍历HDFS目录的PyArrow解决方案
好问题!你说得没错,PyArrow默认的fs.ls()确实只能列出指定HDFS目录下的一级对象。不过不用担心,PyArrow的HDFS连接对象提供了专门的递归遍历API——walk(),它的用法和Python标准库的os.walk()非常相似,能完美实现递归列出所有文件和子文件夹的需求。
使用walk()实现递归遍历
walk()方法会遍历指定目录及其所有子目录,每次返回一个三元组(root, dirs, files):
root: 当前正在遍历的目录路径dirs: 当前root目录下的所有子文件夹名称列表files: 当前root目录下的所有文件名称列表
你可以基于这个方法修改你的代码,获取所有层级的文件和文件夹及其元数据:
import pyarrow as pa # 建立HDFS连接 fs = pa.hdfs.connect() my_path = "/path/to/folder" # 递归遍历目标目录 for root, dirs, files in fs.walk(my_path): # 处理子文件夹 for dir_name in dirs: dir_full_path = f"{root}/{dir_name}" # 获取文件夹的元数据(比如最后修改时间) dir_meta = fs.stat(dir_full_path) print(f'Folder: {dir_full_path}, Last modified: {dir_meta.mtime}') # 处理文件 for file_name in files: file_full_path = f"{root}/{file_name}" file_meta = fs.stat(file_full_path) print(f'File: {file_full_path}, Last modified: {file_meta.mtime}')
简化需求:仅收集所有文件路径
如果你的需求只是获取所有层级的文件路径(不需要文件夹信息),可以简化代码:
import pyarrow as pa fs = pa.hdfs.connect() my_path = "/path/to/folder" all_files = [] # 遍历过程中忽略dirs,只收集files for root, _, files in fs.walk(my_path): all_files.extend([f"{root}/{file}" for file in files]) # 输出所有文件路径 for file_path in all_files: print(file_path)
替代方案:手动递归调用ls()
如果你不想使用walk(),也可以自己实现递归逻辑,通过循环调用ls()并判断对象类型(文件夹则继续递归):
import pyarrow as pa fs = pa.hdfs.connect() my_path = "/path/to/folder" def recursive_ls(path): obj_list = fs.ls(path, True) for obj in obj_list: print(f'{obj["name"]}, {obj["last_modified_time"]}') # 如果是文件夹,递归遍历 if obj["kind"] == "directory": recursive_ls(obj["name"]) # 调用递归函数 recursive_ls(my_path)
不过更推荐使用官方提供的walk()方法,它的实现更高效且代码更简洁。
内容的提问来源于stack exchange,提问作者mehdi




