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

使用Python从Azure Data Lake Gen2指定路径的所有子目录批量下载文件

使用Python从Azure Data Lake Gen2指定路径的所有子目录批量下载文件

嘿,我懂你现在的痛点——你已经能搞定单个文件夹的文件下载,但面对嵌套的子目录就没办法递归处理了对吧?而且原代码还可能遇到子目录里文件名重复导致覆盖的问题,我来帮你调整代码解决这些问题。

首先,先说说你原代码的几个小问题:

  • 调用get_paths时没加recursive=True参数,默认只会返回当前目录下的文件和子目录,不会深入遍历
  • 直接取路径的最后一段作为文件名,要是子目录里有同名文件,下载到本地会被覆盖
  • 没有在本地创建和ADLS里对应的子目录结构,所有文件都会堆在同一个文件夹里

下面是修改后的完整代码,实现了递归遍历所有子目录,并且在本地保留对应的目录结构:

from azure.storage.filedatalake import FileSystemClient, DataLakeServiceClient
from azure.identity import ClientSecretCredential
from pathlib import Path
import os
import logging

# 初始化日志
logging.basicConfig(level=logging.ERROR)
log = logging.getLogger(__name__)

def download_to_local(
    credential: ClientSecretCredential,
    storage_account_name: str,
    file_system_name: str,
    root_directory: str,
    destination_root: str,
):
    # 确保本地根目录存在
    Path(destination_root).mkdir(parents=True, exist_ok=True)

    # 创建DataLake服务客户端
    service_client = DataLakeServiceClient(
        account_url=f"https://{storage_account_name}.dfs.core.windows.net/",
        credential=credential,
    )

    file_system_client = service_client.get_file_system_client(file_system=file_system_name)

    # 递归获取所有文件路径(recursive=True会遍历所有子目录)
    all_paths = file_system_client.get_paths(path=root_directory, recursive=True)

    try:
        for path in all_paths:
            # 跳过目录,只处理文件
            if path.is_directory:
                continue
            
            # 计算文件相对于根目录的相对路径
            relative_path = os.path.relpath(path.name, root_directory)
            # 构建本地保存路径
            local_file_path = os.path.join(destination_root, relative_path)
            # 确保本地子目录存在
            Path(os.path.dirname(local_file_path)).mkdir(parents=True, exist_ok=True)

            # 获取文件客户端并下载
            file_client = file_system_client.get_file_client(path.name)
            download_stream = file_client.download_file()
            downloaded_bytes = download_stream.readall()

            with open(local_file_path, 'wb') as local_file:
                local_file.write(downloaded_bytes)
            
            print(f"已下载文件: {path.name} -> {local_file_path}")

    except Exception as e:
        log.error(f"下载过程中出现错误: {str(e)}")

# 调用示例(替换成你的实际参数)
if __name__ == "__main__":
    # 你的Azure AD凭据
    credential = ClientSecretCredential(
        tenant_id="你的租户ID",
        client_id="你的客户端ID",
        client_secret="你的客户端密钥"
    )

    # ADLS Gen2参数
    storage_account_name = "xyz"
    file_system_name = "abc"
    root_directory = "rock/final_update/ROCK_OrdersDetails"
    destination_root = "/tmp/rock/final_update/ROCK_OrdersDetails"

    download_to_local(credential, storage_account_name, file_system_name, root_directory, destination_root)

关键修改点说明:

  1. 递归遍历:在get_paths里添加recursive=True,这样就能获取到指定根目录下所有层级的文件路径
  2. 保留目录结构:通过os.path.relpath计算文件相对于根目录的路径,然后在本地创建对应的子目录,避免文件覆盖
  3. 跳过目录:判断path.is_directory,只处理文件,跳过目录项
  4. 修正服务客户端URL:原代码的account_url写错了,正确格式应该是https://{storage_account_name}.dfs.core.windows.net/,之前的把file_system_name放进去是错误的

注意事项:

  • 确保你的服务主体(ClientSecretCredential对应的身份)有ADLS Gen2目标路径的读取权限(比如Storage Blob Data Reader角色)
  • 本地路径要确保有足够的读写权限
  • 你使用的azure-storage-file-datalake 12.10.0版本完全支持recursive参数,不用担心版本兼容问题

备注:内容来源于stack exchange,提问作者Kashyap

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.22 11:58:08