使用azure-datalake-store访问ADLS Gen2时报UnboundLocalError求解
访问Azure Data Lake Gen2读取CSV时触发UnboundLocalError问题
原提问场景
您好,我正使用如下代码访问Azure Data Lake Gen2以读取CSV文件:
from azure.datalake.store import core, lib, multithread import pandas as pd tenant_id = '<your Azure AD tenant id>' username = '<your username in AAD>' password = '<your password>' store_name = '<your ADL name>' token = lib.auth(tenant_id, username, password) # 也可以通过注册应用获取client_id和client_secret来生成鉴权token # 如果要在生产环境应用该代码,推荐使用客户端模式完成鉴权 # client_id = '<client id of your app registered in Azure AD, 格式例如 xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx>' # client_secret = '<your client secret>' # token = lib.auth(tenant_id, client_id=client_id, client_secret=client_secret) adl = core.AzureDLFileSystem(token, store_name=store_name) f = adl.open('<your csv file path, 格式例如 data/test.csv>') df = pd.read_csv(f)
填入所有正确参数后,运行时收到如下报错:
----> 5 token = lib.auth(tenant_id, username, password) 6 # Or you can register an app to get client_id and client_secret to get token 7 # If you want to apply this code in your application, I recommended to do the authentication by client /local_disk0/.ephemeral_nfs/envs/pythonEnv--------------/lib/python3.7/site-packages/azure/datalake/store/lib.py in auth(tenant_id, username, password, client_id, client_secret, resource, require_2fa, authority, retry_policy, **kwargs) 148 raise ValueError("No authentication method found for credentials") 149 return out --> 150 out = get_token_internal() 151 152 out.update({'access': out['accessToken'], 'resource': resource, /local_disk0/.ephemeral_nfs/envs/pythonEnv-----------------/lib/python3.7/site-packages/azure/datalake/store/retry.py in f_retry(*args, **kwargs) 104 except: 105 pass --> 106 request_successful = last_exception is None or (response is not None and response.status_code == 401) # 401 = Invalid credentials 107 if request_successful or not retry_policy.should_retry(response, last_exception, retry_count): 108 break UnboundLocalError: local variable 'response' referenced before assignment
已按照操作指引执行但仍然出现该错误,想咨询问题成因:是密钥存在问题,还是需要在Data Lake上完成相关配置?
问题成因与解决方法
这个报错和你填的密钥、Data Lake的权限配置没有直接关系,本质是旧版azure-datalake-store SDK自带的bug:
- 报错触发点在SDK的重试封装逻辑里,当鉴权请求在网络层就失败、根本没拿到Azure服务端的返回结果时,代码没有给
response变量赋默认空值,就直接引用这个变量做判断,最终抛出未定义变量的错误,把真正的底层报错完全覆盖了。 - 一般会触发这个bug的真实场景包括:
- 使用用户名密码(ROPC)的鉴权模式时,Azure AD默认对这类无交互的直接密码登录有严格的安全限制,请求还没走到校验用户名密码的步骤就被安全策略拦截,根本拿不到服务端返回的response
- 代码运行的环境(比如云沙箱、公司内网)到Azure AD鉴权端点的网络不通,请求根本发不出去
- 填入的tenant_id、鉴权对应的资源标识不对,请求直接被DNS层拦截
可按以下步骤排查解决:
- 先绕过SDK的bug拿到真实报错:调用
lib.auth的时候传入参数retry_policy=lambda *args, **kwargs: False,把SDK的重试逻辑完全关掉,此时SDK不会走那段有bug的重试代码,会把真正的异常抛出来,直接定位问题根源 - 换掉不安全的ROPC鉴权:按照代码注释提到的流程,在Azure AD注册应用,使用client_id + client_secret的客户端凭证模式鉴权,记得给这个应用账号分配对应Data Lake存储账号的存储 Blob 数据参与者权限——目前Azure AD对个人、企业账号的直接密码登录基本都是默认关闭的,很容易出现请求发出去就被拦截的情况
- 换掉不兼容的旧SDK:当前使用的
azure-datalake-store是为ADLS Gen1开发的专用SDK,访问Gen2存在长期兼容性问题,建议换成官方维护的azure-storage-file-datalakeSDK,从根源上避免这类不再维护的旧版bug - 检查网络连通性:确认当前运行代码的环境可以正常访问
login.microsoftonline.com这个Azure AD鉴权地址,如果是在公司内网、云沙箱环境运行,要正确配置代理,避免请求发不出去触发SDK的异常。
内容的提问来源于stack exchange,提问作者eserciziator
相关产品推荐
相关产品推荐

