Azure Function Python 写入 Azure DataLake Gen2

Posted

技术标签:

【中文标题】Azure Function Python 写入 Azure DataLake Gen2【英文标题】:Azure Function Python write to Azure DataLake Gen2 【发布时间】:2021-05-19 12:37:41 【问题描述】:

我想使用 Azure 函数和 Python 将文件写入我的 Azure DataLake Gen2。

很遗憾,我遇到了以下身份验证问题:

异常:ClientAuthenticationError:(InvalidAuthenticationInfo) 服务器未能验证请求。请参考 www-authenticate 标头中的信息。

“WWW 验证”:“已编辑”

我的帐户和函数应用都应该具有访问我的 DataLake 所分配的必要角色。

这是我的功能:

import datetime
import logging

from azure.identity import DefaultAzureCredential
from azure.storage.filedatalake import DataLakeServiceClient
import azure.functions as func

def main(mytimer: func.TimerRequest) -> None:
    utc_timestamp = datetime.datetime.utcnow().replace(
        tzinfo=datetime.timezone.utc).isoformat()

    if mytimer.past_due:
        logging.info('The timer is past due!')

    credential = DefaultAzureCredential()
    service_client = DataLakeServiceClient(account_url="https://<datalake_name>.dfs.core.windows.net", credential=credential)

    file_system_client = service_client.get_file_system_client(file_system="temp")
    directory_client = file_system_client.get_directory_client("test")
    file_client = directory_client.create_file("uploaded-file.txt")
    
    file_contents = 'some data'
    file_client.append_data(data=file_contents, offset=0, length=len(file_contents))
    file_client.flush_data(len(file_contents))


    logging.info('Python timer trigger function ran at %s', utc_timestamp)

我错过了什么?

THX & BR

彼得

【问题讨论】:

这对我来说似乎工作正常。你是在本地测试还是在 Azure 上测试? 我都测试过,本地和 Azure 都失败了 直接使用连接字符串怎么样? @BowmanZhu:将 DefaultAzureCredential() 的结果传递给 DataLakeServiceClient 对您有用吗? DefaultAzureCredential 在您这边使用了哪个身份 - VScode、CLI、...? 连接字符串很遗憾由于安全原因被禁用 【参考方案1】:

问题似乎来自 DefaultAzureCredential。

DefaultAzureCredential 使用的标识取决于环境。当需要访问令牌时,它会依次使用这些身份请求一个,当一个提供令牌时停止:

1. A service principal configured by environment variables. 
2. An Azure managed identity. 
3. On Windows only: a user who has signed in with a Microsoft application, such as Visual Studio.
4. The user currently signed in to Visual Studio Code.
5. The identity currently logged in to the Azure CLI.

事实上,您完全可以在不使用默认凭据的情况下生成数据湖服务对象。你可以这样做(直接使用连接字符串连接):

import logging
import datetime

from azure.storage.filedatalake import DataLakeServiceClient
import azure.functions as func


def main(req: func.HttpRequest) -> func.HttpResponse:
    connect_str = "DefaultEndpointsProtocol=https;AccountName=0730bowmanwindow;AccountKey=xxxxxx;EndpointSuffix=core.windows.net"
    utc_timestamp = datetime.datetime.utcnow().replace(
        tzinfo=datetime.timezone.utc).isoformat()

    service_client = DataLakeServiceClient.from_connection_string(connect_str)

    file_system_client = service_client.get_file_system_client(file_system="test")
    directory_client = file_system_client.get_directory_client("test")
    file_client = directory_client.create_file("uploaded-file.txt")
    
    file_contents = 'some data'
    file_client.append_data(data=file_contents, offset=0, length=len(file_contents))
    file_client.flush_data(len(file_contents))

    return func.HttpResponse(
            "Test.",
            status_code=200
    )

另外,为了保证数据写入顺畅,请检查您的datalake是否有访问限制。

【讨论】:

我的问题是由于安全原因,Datalake 的连接字符串被禁用。 DefaultAzureCredential 正在使用我的 CLI 身份,该身份在 DataLake 上有足够的权限。 @IntoNumbers 好的,我明天会尝试重现同样的问题,现在有一些事情要做。感谢您的回复。:) 那太好了,非常感谢! 但是我在 AzureCliCredential() 上取得了成功,并且由于事实上,它现在似乎是 Azure 中的角色分配问题,我会接受你的回答。再次感谢您的努力! BR彼得 是的,它确实可以在本地使用 AzureCliCredential()【参考方案2】:

Bowman Zhu 建议的函数包含错误。根据Azure documentation,参数“length”需要以字节为单位的长度。但是,建议的函数使用字符长度。其中一些字符可能由多个字节组成。在这种情况下,该函数不会将file_contents的所有字节都写入文件,从而导致数据丢失!

因此,

file_client.append_data(data=file_contents, offset=0, length=len(file_contents))
file_client.flush_data(len(file_contents))

必须是这样的:

length = len(file_contents.encode())
file_client.append_data(data=file_contents, offset=0, length=length)
file_client.flush_data(offset=length)

【讨论】:

以上是关于Azure Function Python 写入 Azure DataLake Gen2的主要内容,如果未能解决你的问题,请参考以下文章

将 Python DataFrame 作为 CSV 写入 Azure Blob

Azure Functions - 写入表输出绑定时处理错误

Azure 应用服务Python fastapi Function在Azure

Azure Function (python) insert to Azure SQL 不断收到错误

使用托管标识从 Azure Logic 应用向 Azure Function 进行身份验证

Azure(函数)参数在 Python 中声明,但不在 function.json 中