Azure Python SDK遍历Blob跨存储拷贝仅复制最后一个文件问题求助
问题根因
你的代码核心问题是缩进逻辑错误:拷贝Blob的代码块没有放在遍历Blob的内层循环for blob in blobs_list的范围内,仅在每个容器的所有Blob遍历完成后执行一次拷贝,此时blob变量存储的是当前容器最后一个Blob的信息,所以每个容器只会复制最后一个文件,也不会同步新增的其他文件。
同时你的代码还存在几个可优化的问题:
- 重复实例化源端
BlobServiceClient,属于冗余代码 - 目标端
BlobServiceClient在循环中反复创建,无意义且降低执行效率 - 使用裸
except捕获所有异常,容易掩盖权限、网络等其他报错,不便于后续问题排查
修正后的完整代码
from typing import Container from azure.storage.blob import BlobClient, BlobServiceClient, ContainerClient from azure.storage.blob import ResourceTypes, AccountSasPermissions from azure.storage.blob import generate_account_sas from datetime import datetime, timedelta from azure.core.exceptions import ResourceExistsError today = str(datetime.now().date()) print(today) # ================================ 源端配置 =============================== source_connection_string = '' # 源存储账号连接字符串 source_account_key = '' # 源存储账号密钥 # 创建源端客户端 仅需实例化一次 source_blob_service_client = BlobServiceClient.from_connection_string(source_connection_string) # ================================ 目标端配置 =============================== target_connection_string = '' # 目标存储账号连接字符串 # 创建目标端客户端 仅需实例化一次 target_blob_service_client = BlobServiceClient.from_connection_string(target_connection_string) # 遍历源端所有容器 for container in source_blob_service_client.list_containers(include_metadata=True): container_name = container['name'] print(f"当前处理容器: {container_name}, 元数据: {container['metadata']}") print("==========================") # 生成账号级SAS令牌 每个容器生成一次即可 sas_token = generate_account_sas( account_name = source_blob_service_client.account_name, account_key = source_account_key, resource_types = ResourceTypes(object=True, container=True), permission= AccountSasPermissions(read=True,list=True), expiry = datetime.utcnow() + timedelta(hours=4) ) # 获取当前源容器客户端 source_container_client = source_blob_service_client.get_container_client(container_name) # 遍历当前容器下所有Blob for blob in source_container_client.list_blobs(): blob_name = blob.name print(f"当前处理Blob: {blob_name}") # 构造源Blob访问地址 source_blob_client = BlobClient( source_blob_service_client.url, container_name = container_name, blob_name = blob_name, credential = sas_token ) # 目标容器命名规则:原容器名+日期 可按需调整 target_container_name = f"{container_name}{today}" # 先创建目标容器 不存在则创建 存在则跳过 try: target_blob_service_client.create_container(target_container_name) print(f"已创建目标容器: {target_container_name}") except ResourceExistsError: # 容器已存在无需处理 pass # 执行Blob拷贝 target_blob_client = target_blob_service_client.get_blob_client(target_container_name, blob_name) target_blob_client.start_copy_from_url(source_blob_client.url) print(f"已提交拷贝任务: {blob_name} -> {target_container_name}")
验证说明
修正后所有Blob的拷贝逻辑都会在内层循环中逐文件执行,每个容器下的所有文件都会被复制到目标存储对应容器中,新增文件重新运行脚本也会正常同步。
内容的提问来源于stack exchange,提问作者Nayden Van
相关产品推荐
相关产品推荐

