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

Azure Blob存储中Python脚本添加CSV到Excel报错求助

问题:Azure Blob存储中Excel文件添加工作表失败,出现域名解析错误

我有一个存储在Azure Blob中的Excel文件,包含4个工作表(tab2、tab3、tab4、tab6),需要把两个CSV文件分别作为第一个工作表(tab1)和倒数第二个工作表(tab5)添加进去,编写的Python脚本如下:

from azure.storage.blob import BlobServiceClient
import pandas as pd
from io import BytesIO
from datetime import date

today = date.today().strftime("%Y%m%d")


connection_string = "DefaultEndpointsProtocol=https;AccountName=MyAccount;AccountKey=accountkey;EndpointSuffix=myendpoint.blob.core.windows.net/myproj"

container_name = "MyContainer/Prj1"
excel_blob_name = "My Excel.xlsx"
csv_blob_1_name = "My_csv1_"+today+".csv"
csv_blob_2_name = "My_csv2_"+today+".csv"

# Initialize Blob Service Client
blob_service_client = BlobServiceClient.from_connection_string(connection_string)

# Read Excel file from Blob Storage
excel_blob_client = blob_service_client.get_blob_client(container=container_name, blob=excel_blob_name)
excel_blob_data = BytesIO(excel_blob_client.download_blob().readall())

# Read CSV files from Blob Storage
csv_blob_client_1 = blob_service_client.get_blob_client(container=container_name, blob=csv_blob_1_name)
csv_blob_data_1 = BytesIO(csv_blob_client_1.download_blob().readall())
df_csv_1 = pd.read_csv(csv_blob_data_1)

csv_blob_client_2 = blob_service_client.get_blob_client(container=container_name, blob=csv_blob_2_name)
csv_blob_data_2 = BytesIO(csv_blob_client_2.download_blob().readall())
df_csv_2 = pd.read_csv(csv_blob_data_2)

# Load the Excel file in memory
with pd.ExcelWriter(excel_blob_data, mode="a", engine="openpyxl") as excel_writer:
    df_csv_1.to_excel(excel_writer, sheet_name="tab1", index=False)
    df_csv_2.to_excel(excel_writer, sheet_name="tab5", index=False)

# Save modified Excel file back to Blob Storage
excel_blob_data.seek(0)  # Reset stream position
excel_blob_client.upload_blob(excel_blob_data, overwrite=True)

运行脚本时出现以下域名解析错误:

Traceback (most recent call last):
  File "d:\batch\tasks\workitems\adfv2-ProjCont\job-1\3e150412-3328-4b72-b09b-29494f29396b\wd\csv_join_excel.py", line 23, in <module>
    excel_blob_data = BytesIO(excel_blob_client.download_blob().readall())
                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python312\Lib\site-packages\azure\core\tracing\decorator.py", line 119, in wrapper_use_tracer
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python312\Lib\site-packages\azure\storage\blob\_blob_client.py", line 753, in download_blob
    return StorageStreamDownloader(**options)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python312\Lib\site-packages\azure\storage\blob\_download.py", line 403, in __init__
    self._response = self._initial_request()
                     ^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python312\Lib\site-packages\azure\storage\blob\_download.py", line 456, in _initial_request
    location_mode, response = cast(Tuple[Optional[str], Any], self._clients.blob.download(
                                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python312\Lib\site-packages\azure\core\tracing\decorator.py", line 119, in wrapper_use_tracer
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python312\Lib\site-packages\azure\storage\blob\_generated\operations\_blob_operations.py", line 1641, in download
    pipeline_response: PipelineResponse = self._client._pipeline.run(  # pylint: disable=protected-access
                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python312\Lib\site-packages\azure\core\pipeline\_base.py", line 242, in run
    return first_node.send(pipeline_request)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python312\Lib\site-packages\azure\core\pipeline\_base.py", line 98, in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python312\Lib\site-packages\azure\core\pipeline\_base.py", line 98, in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python312\Lib\site-packages\azure\core\pipeline\_base.py", line 98, in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
  [Previous line repeated 2 more times]
  File "C:\Program Files\Python312\Lib\site-packages\azure\core\pipeline\policies\_redirect.py", line 205, in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python312\Lib\site-packages\azure\core\pipeline\_base.py", line 98, in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python312\Lib\site-packages\azure\storage\blob\_shared\policies.py", line 555, in send
    raise err
  File "C:\Program Files\Python312\Lib\site-packages\azure\storage\blob\_shared\policies.py", line 527, in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python312\Lib\site-packages\azure\core\pipeline\_base.py", line 98, in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python312\Lib\site-packages\azure\core\pipeline\_base.py", line 98, in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python312\Lib\site-packages\azure\core\pipeline\_base.py", line 98, in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
  [Previous line repeated 1 more time]
  File "C:\Program Files\Python312\Lib\site-packages\azure\storage\blob\_shared\policies.py", line 301, in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python312\Lib\site-packages\azure\core\pipeline\_base.py", line 98, in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python312\Lib\site-packages\azure\core\pipeline\_base.py", line 98, in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python312\Lib\site-packages\azure\core\pipeline\_base.py", line 130, in send
    self._sender.send(request.http_request, **request.context.options),
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python312\Lib\site-packages\azure\storage\blob\_shared\base_client.py", line 353, in send
    return self._transport.send(request, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python312\Lib\site-packages\azure\core\pipeline\transport\_requests_basic.py", line 409, in send
    raise error
azure.core.exceptions.ServiceRequestError: <urllib3.connection.HTTPSConnection object at 0x00000222F95FA240>: Failed to resolve 'odsblobcontainer.blob.odsblobcontainer.blob.core.windows.net' ([Errno 11001] getaddrinfo failed)

问题根源与修复方案

1. 连接字符串格式错误

你的connection_string中EndpointSuffix字段包含了额外的路径/myproj,这会导致SDK生成错误的Blob服务域名(重复拼接容器名),触发解析失败。正确的EndpointSuffix应该仅为Blob服务的后缀,比如公有云Azure的core.windows.net。

2. 容器名称格式错误

Blob存储的容器名称不能包含斜杠,MyContainer/Prj1是错误格式,Prj1应该作为Blob路径的一部分,而非容器名称的一部分。

3. 工作表顺序控制问题

原脚本使用mode="a"追加工作表,无法保证tab1在最前、tab5在倒数第二的位置,需要读取所有原工作表后按指定顺序重新写入。


修正后的完整脚本

from azure.storage.blob import BlobServiceClient
import pandas as pd
from io import BytesIO
from datetime import date

today = date.today().strftime("%Y%m%d")

# 修正连接字符串:EndpointSuffix仅保留服务后缀
connection_string = "DefaultEndpointsProtocol=https;AccountName=MyAccount;AccountKey=accountkey;EndpointSuffix=core.windows.net"

# 修正容器与Blob路径:容器名仅为MyContainer,Prj1作为Blob路径前缀
container_name = "MyContainer"
excel_blob_name = "Prj1/My Excel.xlsx"
csv_blob_1_name = "Prj1/My_csv1_"+today+".csv"
csv_blob_2_name = "Prj1/My_csv2_"+today+".csv"

# 初始化Blob服务客户端
blob_service_client = BlobServiceClient.from_connection_string(connection_string)

# 读取Blob中的Excel文件
excel_blob_client = blob_service_client.get_blob_client(container=container_name, blob=excel_blob_name)
excel_blob_data = BytesIO(excel_blob_client.download_blob().readall())

# 读取原Excel的所有工作表,用于控制顺序
xls = pd.ExcelFile(excel_blob_data)
sheet_dict = {sheet_name: xls.parse(sheet_name) for sheet_name in xls.sheet_names}

# 读取第一个CSV文件
csv_blob_client_1 = blob_service_client.get_blob_client(container=container_name, blob=csv_blob_1_name)
csv_blob_data_1 = BytesIO(csv_blob_client_1.download_blob().readall())
df_csv_1 = pd.read_csv(csv_blob_data_1)

# 读取第二个CSV文件
csv_blob_client_2 = blob_service_client.get_blob_client(container=container_name, blob=csv_blob_2_name)
csv_blob_data_2 = BytesIO(csv_blob_client_2.download_blob().readall())
df_csv_2 = pd.read_csv(csv_blob_data_2)

# 按指定顺序组织工作表:tab1 -> 原tab2、tab3、tab4 -> tab5 -> tab6
new_sheets = [
    ("tab1", df_csv_1),
    ("tab2", sheet_dict["tab2"]),
    ("tab3", sheet_dict["tab3"]),
    ("tab4", sheet_dict["tab4"]),
    ("tab5", df_csv_2),
    ("tab6", sheet_dict["tab6"])
]

# 写入新的Excel文件到内存流
output_excel = BytesIO()
with pd.ExcelWriter(output_excel, engine="openpyxl") as excel_writer:
    for sheet_name, df in new_sheets:
        df.to_excel(excel_writer, sheet_name=sheet_name, index=False)

# 将修改后的Excel文件上传回Blob存储
output_excel.seek(0)
excel_blob_client.upload_blob(output_excel, overwrite=True)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 21:24:56