python + Azure Cosmos DB (非常规方法)
1.作为一个数据库服务,使用之前需要一个数据库的账户。
这个账户可以在portal上做成,叫做Azure Cosmos DB Account
下面这张官网上的图片很好的反应了Azure Cosmos DB 的逻辑结构
一个Azure Cosmos DB Account下面可以有很多个database,
database有点像一个namesapce,他可以包含多个container
而数据是存放在container里面的。
2.python访问Azure Cosmos DB,必须先有一个CosmosClient class。
它负责执行所有的request。然后才能创建database,container等等。
实例化这个class的方式有2种:
①Azure Cosmos DB Account 和 its primary master key 。
②用AAD credentials 和 the azure identity package
使用AAD credentials 的话,需要在azure 上注册一个app。详细的步骤可以参考下面的链接。
Authenticate to Azure resources from Python apps hosted on-premises | Microsoft Learn
官方推荐用the azure identity package,所以今天来研究这种方式
import os
from azure.cosmos import CosmosClient,exceptions
from azure.identity import DefaultAzureCredential
#创建环境变量
endpoint=os.environ["COSMOS_ENDPOINT"]
#create cosmosclient
credential = DefaultAzureCredential()
client=CosmosClient(url=endpoint,credential=credential)
#
#定义数据库名称,容器名称
#DATABASE_NAME = "cosmicwork"
CONTAINER_NAME = "products"
DATABASE_NAME = "database001"
#create databases
try:
database=client.create_database(DATABASE_NAME)
except exceptions.CosmosResourceExistsError:
database=client.get_database_client(DATABASE_NAME)
注意:事先需要设置环境变量COSMOS_ENDPOINT
需要用Azure CLI来执行
$env:COSMOS_ENDPOINT = "<cosmos-account-URI>"
报错了
Traceback (most recent call last):
File "C:\xxxxxx\Dev\cosmosDB.py", line 16, in <module>
database=client.create_database(DATABASE_NAME)
File "xxxxxxxxxxxxx\AppData\Local\Programs\Python\Python310\lib\site-packages\azure\core\tracing\decorator.py", line 76, in wrapper_use_tracer
return func(*args, **kwargs)
File "xxxxxxxxxxxxx\AppData\Local\Programs\Python\Python310\lib\site-packages\azure\cosmos\cosmos_client.py", line 280, in create_database
result = self.client_connection.CreateDatabase(database=dict(id=id), options=request_options, **kwargs)
File "xxxxxxxxxxxxx\AppData\Local\Programs\Python\Python310\lib\site-packages\azure\cosmos\_cosmos_client_connection.py", line 322, in CreateDatabase
return self.Create(database, path, "dbs", None, None, options, **kwargs)
File "xxxxxxxxxxxxx\AppData\Local\Programs\Python\Python310\lib\site-packages\azure\cosmos\_cosmos_client_connection.py", line 2176, in Create
result, self.last_response_headers = self.__Post(path, request_params, body, headers, **kwargs)
File "xxxxxxxxxxxxx\AppData\Local\Programs\Python\Python310\lib\site-packages\azure\cosmos\_cosmos_client_connection.py", line 2342, in __Post
return synchronized_request.SynchronizedRequest(
File "xxxxxxxxxxxxx\AppData\Local\Programs\Python\Python310\lib\site-packages\azure\cosmos\_synchronized_request.py", line 206, in SynchronizedRequest
return _retry_utility.Execute(
File "xxxxxxxxxxxxx\AppData\Local\Programs\Python\Python310\lib\site-packages\azure\cosmos\_retry_utility.py", line 83, in Execute
result = ExecuteFunction(function, global_endpoint_manager, *args, **kwargs)
File "xxxxxxxxxxxxx\AppData\Local\Programs\Python\Python310\lib\site-packages\azure\cosmos\_retry_utility.py", line 143, in ExecuteFunction
return function(*args, **kwargs)
File "xxxxxxxxxxxxx\AppData\Local\Programs\Python\Python310\lib\site-packages\azure\cosmos\_synchronized_request.py", line 154, in _Request
raise exceptions.CosmosHttpResponseError(message=data, response=response)
azure.cosmos.exceptions.CosmosHttpResponseError: (Forbidden) Request blocked by Auth xxxxxxcosmosdb : The given request [POST /dbs] cannot be authorized by AAD token in data plane. Learn more: https://aka.ms/cosmos-native-rbac.
ActivityId: 1753a765-b224-474b-a2ec-607c7f2897e3, Microsoft.Azure.Documents.Common/2.14.0
Code: Forbidden
Message: Request blocked by Auth xxxxxxcosmosdb : The given request [POST /dbs] cannot be authorized by AAD token in data plane. Learn more: https://aka.ms/cosmos-native-rbac.
ActivityId: aaaaaaaaaaaaaa, Microsoft.Azure.Documents.Common/2.14.0
看起来像是权限问题,查了好久。
这里用到的是DefaultAzureCredential这个class。他是怎么认证request的呢?
关于认证,
运行在on-premises 和运行在Azure的Python apps ,认证方式也是不同的。
DefaultAzureCredential支持多种认证方式,
比如这个例子,本地开发时,使用Azure cli的方式登录到azure,
deploy 到azure上以后使用同一个账户。
无论哪种方式,本地开发的user account,需要被正确配置RBAC。
那么先做一个role,然后再把role赋给本地vscode执行az login时登录的用户。
①创建role
az cosmosdb sql role definition create \
--account-name <cosmosdb-account-name> \
--resource-group <resource-group-name> \
--body '{
"RoleName": "PasswordlessReadWrite",
"Type": "CustomRole",
"AssignableScopes": ["/"],
"Permissions": [{
"DataActions": [
"Microsoft.DocumentDB/databaseAccounts/readMetadata",
"Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/*",
"Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/*"
]
}]
}'
②把role 付给用户
az cosmosdb sql role assignment create \
--account-name <cosmosdb-account-name> \
--resource-group <resource-group-name> \
--scope "/" \
--principal-id <your-user-id> \
--role-definition-id <your-custom-role-id>
依然不能行噢噢噢噢
从下面这个资料来看,像是不能用?
Quickstart - Azure Cosmos DB for NoSQL client library for Python | Microsoft Learn
改用Azure CLI来创建databease
# Create a SQL API database `
az cosmosdb sql database create `
--account-name <cosmos-db-account-name> `
--resource-group <resource-group-name> `
--name cosmicworks
创建成功了。
3.有了database,现在就可创建container了
# Create a SQL API container
az cosmosdb sql container create `
--account-name <cosmos-db-account-name> `
--resource-group <resource-group-name> `
--database-name cosmicworks `
--partition-key-path "/categoryId" `
--name products
4.最后一步,就是插入数据啦
for i in range(1, 10):
container.upsert_item({
'id': 'item{0}'.format(i),
'productName': 'Widget',
'productModel': 'Model {0}'.format(i)
}
)
参考资料:
Disclaimer — Azure SDK for Python 2.0.0 documentation (windows.net)
Quickstart - Azure Cosmos DB for NoSQL client library for Python | Microsoft Learn
Overview: Authenticate Python apps to Azure using the Azure SDK | Microsoft Learn
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: