示例:使用适用于 Python 的 Azure 库来访问 Azure 存储

本文介绍如何在 Python 应用程序代码中使用 Azure 客户端库将文件上传到 Azure Blob 存储容器。 本文假定已创建示例:创建 Azure 存储中所示的资源。

除非另行说明,否则本文中的所有资源在 Linux/macOS bash 和 Windows 命令行界面上的工作方式相同。

1:设置本地开发环境

如果尚未设置,则请设置一个可在其中运行此代码的环境。 提供以下选择:

2:安装库包

requirements.txt 文件中,为要使用的客户端库包添加行并保存此文件。

azure-storage-blob
azure-identity

然后,在终端或命令提示符中安装规定的内容。

pip install -r requirements.txt

3:创建要上传的文件

创建名为 sample-source.txt 的源文件。 此文件名为该代码所需的内容。

Hello there, Azure Storage. I'm a friendly file ready to be stored in a blob.

4:从应用代码使用 Blob 存储

以下两节演示了访问通过示例:创建 Azure 存储所创建 Blob 容器的两种方法。

第一种方法(使用身份验证)会使用 DefaultAzureCredential 对应用进行身份验证,如使用服务主体在本地开发期间将 Python 应用验证到 Azure 服务。 使用此方法时,必须先为应用标识分配适当的权限,而这仅为建议的做法。

第二种方法(使用连接字符串)会使用连接字符串来直接访问存储帐户。 尽管此方法看起来更简单,但它有两个重大缺点:

  • 连接字符串在本质上使用存储帐户(而不是该帐户中的单个资源)来验证连接代理。 因此,连接字符串授予的授权范围可能会超出所需的范围。

  • 由于连接字符串包含纯文本形式的访问信息,因此如果未正确构造或保护该连接字符串,则可能存在潜在漏洞。 如果公开此类连接字符串,则可使用它来访问存储帐户下的各种资源。

出于这些原因,建议在生产代码中使用该身份验证方法。

4a:将 Blob 存储与身份验证配合使用

  1. 使用以下代码创建一个名为“use_blob_auth py”的文件。 注释对步骤进行了说明。

    import os
    import uuid
    
    from azure.identity import DefaultAzureCredential
    
    # Import the client object from the SDK library
    from azure.storage.blob import BlobClient
    
    credential = DefaultAzureCredential()
    
    # Retrieve the storage blob service URL, which is of the form
    # https://<your-storage-account-name>.blob.core.windows.net/
    storage_url = os.environ["AZURE_STORAGE_BLOB_URL"]
    
    # Create the client object using the storage URL and the credential
    blob_client = BlobClient(
        storage_url,
        container_name="blob-container-01",
        blob_name=f"sample-blob-{str(uuid.uuid4())[0:5]}.txt",
        credential=credential,
    )
    
    # Open a local file and upload its contents to Blob Storage
    with open("./sample-source.txt", "rb") as data:
        blob_client.upload_blob(data)
        print(f"Uploaded sample-source.txt to {blob_client.url}")
    

    参考链接:

  2. 创建名为 AZURE_STORAGE_BLOB_URL 的环境变量:

    set AZURE_STORAGE_BLOB_URL=https://pythonazurestorage12345.blob.core.windows.net
    

    将“pythonazurestorage12345”替换为存储帐户的名称。

    AZURE_STORAGE_BLOB_URL 环境变量仅由此示例使用。 Azure 库不会使用它。

  3. 使用 az ad sp create-for-rbac 命令为应用创建新的服务主体。 该命令会同时为应用创建应用注册。 为服务主体指定所选名称。

    az ad sp create-for-rbac --name {service-principal-name}
    

    此命令的输出如下所示。 记下这些值或使此窗口保持打开状态,因为在下一步中需使用这些值,且无法再次查看密码(客户端密码)值。 但是,如果需要,可稍后添加新密码,而不会使服务主体或现有密码失效。

    {
      "appId": "00000000-0000-0000-0000-000000000000",
      "displayName": "{service-principal-name}",
      "password": "abcdefghijklmnopqrstuvwxyz",
      "tenant": "11111111-1111-1111-1111-111111111111"
    }
    

    可以在 Azure Cloud Shell 中或装有 Azure CLI 的工作站上运行 Azure CLI 命令。

  4. 为应用程序服务主体创建环境变量:

    使用上一命令输出中的值创建以下环境变量。 这些变量会指示 DefaultAzureCredential 使用应用程序服务主体。

    • AZURE_CLIENT_ID → 应用 ID 值。
    • AZURE_TENANT_ID → 租户 ID 值。
    • AZURE_CLIENT_SECRET → 为应用生成的密码/凭据。
    set AZURE_CLIENT_ID=00000000-0000-0000-0000-000000000000
    set AZURE_TENANT_ID=11111111-1111-1111-1111-111111111111
    set AZURE_CLIENT_SECRET=abcdefghijklmnopqrstuvwxyz
    
  5. 尝试运行代码(有意失败):

    python use_blob_auth.py
    
  6. 请注意错误“此请求无权使用此权限执行该操作”。由于正在使用的本地服务主体尚无权访问 Blob 容器,因此会出现此错误。

  7. 使用 az role assignment create Azure CLI 命令向服务主体授予 Blob 容器的参与者权限:

    az role assignment create --assignee <AZURE_CLIENT_ID> \
        --role "Storage Blob Data Contributor" \
        --scope "/subscriptions/<AZURE_SUBSCRIPTION_ID>/resourceGroups/PythonAzureExample-Storage-rg/providers/Microsoft.Storage/storageAccounts/pythonazurestorage12345/blobServices/default/containers/blob-container-01"
    

    --assignee 参数标识了服务主体。 将 <AZURE_CLIENT_ID> 占位符替换为服务主体的应用 ID。

    --scope 参数标识此角色分配适用的位置。 在此示例中,向名为“blob-container-01”的容器的服务主体授予“存储 Blob 数据参与者”角色。

    • PythonAzureExample-Storage-rgpythonazurestorage12345 分别替换为包含存储帐户的资源组以及存储帐户的实际名称。 此外,如有必要,请调整 Blob 容器的名称。 如果使用错误名称,会发现错误“无法对嵌套资源执行请求的操作。 找不到父资源‘pythonazurestorage12345’”。

    • 将 <AZURE_SUBSCRIPTION_ID> 占位符替换为 Azure 订阅 ID。 (可运行 az account show 命令,然后从输出中的 id 属性获取订阅 ID。)

    提示

    如果使用 bash shell 时角色分配命令返回错误“找不到连接适配器”,则请尝试设置 export MSYS_NO_PATHCONV=1 以避免路径转换。 有关详细信息,请参阅此问题

  8. 花一两分钟时间等待权限传播,然后再次运行该代码,验证它现在是否正常工作。 如果再次看到权限错误,请等待更长的时间,然后重试代码。

有关角色分配的详细信息,请参阅如何使用 Azure CLI 分配角色权限

4b:使用带有连接字符串的 Blob 存储

  1. 创建包含以下代码的名为“use_blob_conn_string.py”的 Python 文件。 注释对步骤进行了说明。

    import os
    import uuid
    
    # Import the client object from the SDK library
    from azure.storage.blob import BlobClient
    
    # Retrieve the connection string from an environment variable. Note that a
    # connection string grants all permissions to the caller, making it less
    # secure than obtaining a BlobClient object using credentials.
    conn_string = os.environ["AZURE_STORAGE_CONNECTION_STRING"]
    
    # Create the client object for the resource identified by the connection
    # string, indicating also the blob container and the name of the specific
    # blob we want.
    blob_client = BlobClient.from_connection_string(
        conn_string,
        container_name="blob-container-01",
        blob_name=f"sample-blob-{str(uuid.uuid4())[0:5]}.txt",
    )
    
    # Open a local file and upload its contents to Blob Storage
    with open("./sample-source.txt", "rb") as data:
        blob_client.upload_blob(data)
        print(f"Uploaded sample-source.txt to {blob_client.url}")
    
  2. 创建一个名为 AZURE_STORAGE_CONNECTION_STRING 的环境变量,其值是存储帐户的完整连接字符串。 (此环境变量也被各种 Azure CLI 注释使用。)可通过运行 az storage account show-connection-string 命令来获取存储帐户的连接字符串。

    az storage account show-connection-string --resource-group PythonAzureExample-Storage-rg --name pythonazurestorage12345
    

    PythonAzureExample-Storage-rgpythonazurestorage12345 分别替换为包含存储帐户的资源组以及存储帐户的实际名称。

    设置此环境变量时,请使用输出中 connectionString 属性的整个值(包括引号)。

  3. 运行代码:

    python use_blob_conn_string.py
    

同样,虽然此方法很简单,但连接字符串会授权存储帐户中的所有操作。 对于生产代码,最好使用上一节中所述的特定权限。

5:验证 Blob 创建

运行任一方法的代码后,转到 Azure 门户,导航到 Blob 容器以验证是否存在其内容与 sample-source.txt 文件相同且名为 ssample-blob-{random}.txt 的新 Blob:

blob 容器的 Azure 门户页面,显示已上传的文件

如果已创建名为 AZURE_STORAGE_CONNECTION_STRING 的环境变量,则还可使用 Azure CLI 并通过 az storage blob list 命令来验证该 Blob 是否存在:

az storage blob list --container-name blob-container-01

如果已按说明使用附带身份验证的 Blob 存储,则可使用存储帐户的连接字符串将 --connection-string 参数添加到上述命令。 若要了解如何获取此连接字符串,请参阅 4b:将 Blob 存储与连接字符串配合使用中的说明。 使用包括引号在内的整个连接字符串。

6:清理资源

如果无需保留在此示例中使用的资源组和存储资源,则请运行 az group delete 命令。 资源组不会在订阅中产生任何持续费用,但资源组中的资源(如存储帐户)则可能会产生费用。 最好清理未主动使用的所有组。 --no-wait 参数允许命令立即返回,而不是等到操作完成再返回。

az group delete -n PythonAzureExample-Storage-rg  --no-wait

你还可以使用 ResourceManagementClient.resource_groups.begin_delete 方法从代码中删除资源组。 示例:创建资源组中的代码演示了相关用法。

如果已按说明使用 Blob 存储和身份验证,则最好删除已创建的应用程序服务主体。 可使用 az ad app delete 命令。 将 <AZURE_CLIENT_ID> 占位符替换为服务主体的应用 ID。

az ad app delete --id <AZURE_CLIENT_ID>

另请参阅