#python #python-3.x #amazon-web-services
Вопрос:
Я вызываю API ценообразования AWS, чтобы получить почасовую стоимость своих инстансов EC2, и это пример того, что я получаю за их цены по требованию:
{"OnDemand": {
"QA3NBPZEQKZ2K9AR.JRTCKXETXF": {
"effectiveDate": "2021-08-01T00:00:00Z",
"offerTermCode": "JRTCKXETXF",
"priceDimensions": {
"QA3NBPZEQKZ2K9AR.JRTCKXETXF.6YS6EN2CT7": {
"appliesTo": [],
"beginRange": "0",
"description": "$0.0208 per On Demand Linux t3.small Instance Hour",
"endRange": "Inf",
"pricePerUnit": {
"USD": "0.0208000000"
},
"rateCode": "QA3NBPZEQKZ2K9AR.JRTCKXETXF.6YS6EN2CT7",
"unit": "Hrs"
}
},
"sku": "QA3NBPZEQKZ2K9AR",
"termAttributes": {}
}
}
}
Моя цель-получить цену за единицу стоимости, и я мог бы легко сделать это, сделав что-то вроде:
hourly_cost = price_list['OnDemand']['QA3NBPZEQKZ2K9AR.JRTCKXETXF']['priceDimensions']['QA3NBPZEQKZ2K9AR.JRTCKXETXF.6YS6EN2CT7']['pricePerUnit']['USD']
Однако ключи, такие как «QA3NBPZEQKZ2K9AR.JRTCKXETXF» и «QA3NBPZEQKZ2K9AR.JRTCKXETXF.6YS6EN2CT7», заполняются случайным образом для каждого экземпляра EC2, поэтому я не могу использовать эти два значения для извлечения данных для всех экземпляров.
Я ищу способ пропустить эти два ключа и получить скидку.
Комментарии:
1. Где ключ
['OnDemand']
?2. @It_is_Chris Есть ключ с именем «По требованию», значение которого соответствует приведенному выше словарю
3. Словарь должен быть
{'OnDemand': {...}}
4. @It_is_Chris Я обновил код. Надеюсь, теперь в этом больше смысла. Как бы вы продолжили решать эту проблему?
Ответ №1:
Вы можете использовать регулярное выражение в качестве ключа для этих полей
import re
d[re.compile('[w]*')]
Хотя использование регулярного выражения в качестве ключа не рекомендуется
Ответ №2:
Если рекурсия не является проблемой, и в этом словаре есть данные для нескольких экземпляров, то, возможно, имеет смысл преобразовать их в именованные элементы. Затем вы можете создать коллекцию экземпляров с их ценовыми данными. Особенно, если к данным о ценах необходимо получить доступ позже несколько раз для агрегирования с другими экземплярами, это может упростить привязку к именам. Вот пример кода для такой идеи.
from collections import namedtuple
x = {"OnDemand": {
"QA3NBPZEQKZ2K9AR.JRTCKXETXF": {
"effectiveDate": "2021-08-01T00:00:00Z",
"offerTermCode": "JRTCKXETXF",
"priceDimensions": {
"QA3NBPZEQKZ2K9AR.JRTCKXETXF.6YS6EN2CT7": {
"appliesTo": [],
"beginRange": "0",
"description": "$0.0208 per On Demand Linux t3.small Instance Hour",
"endRange": "Inf",
"pricePerUnit": {
"USD": "0.0208000000"
},
"rateCode": "QA3NBPZEQKZ2K9AR.JRTCKXETXF.6YS6EN2CT7",
"unit": "Hrs"
}
},
"sku": "QA3NBPZEQKZ2K9AR",
"termAttributes": {}
}
}
}
InstanceData = namedtuple('InstanceData', ['Instancekey','priceDimensions'])
InstancePriceDimensions = namedtuple(
'InstancePriceDimensions',
['InstanceKey', 'PriceDimensionKey','pricePerUnit']
)
InstanceDataCollection = []
InstancePriceCollection = []
for key, value in x["OnDemand"].items():
InstanceDataCollection.append(InstanceData(key, value))
for x, val in value["priceDimensions"].items():
if "pricePerUnit" in val:
InstancePriceCollection.append(
InstancePriceDimensions(
key,
x,
val["pricePerUnit"]
)
)
print(InstancePriceCollection)
for x in InstancePriceCollection:
#aggregate the metric over whole collection or process them
print(x.pricePerUnit['USD'])
Ответ №3:
Вы можете использовать dict.keys()
предположение, что структура такая же
k1 = list(d['OnDemand'].keys())[0]
k2 = list(d['OnDemand'][k1]['priceDimensions'].keys())[0]
d['OnDemand'][k1]['priceDimensions'][k2]['pricePerUnit']['USD']
Ответ №4:
Глядя на структуру ответа JSON, я думаю, что у вас есть несколько вариантов здесь.
Поскольку вложенные объекты с такими ключами QA3NBPZEQKZ2K9AR.JRTCKXETXF
по сути являются оболочками вокруг другого подобъекта, вам не обязательно беспокоиться о поиске по списку объектов в поисках любого или всего pricePerUnit
, вы можете просто получить доступ к списку значений и извлечь первое значение:
# pulls the value associated with the key `QA3NBPZEQKZ2K9AR.JRTCKXETXF`
outer = list(price_list['OnDemand'].values())[0]
# pulls the value associated with the key `QA3NBPZEQKZ2K9AR.JRTCKXETXF.6YS6EN2CT7`
inner = list(outer["priceDimensions"].values())[0]
price_per_unit = inner["pricePerUnit"]
Если структура JSON изменится в будущем, вам, возможно, потребуется решить проблемы с индексированием, при этом либо внутренний, либо внешний будет выдавать пустой список значений, либо аналогичные ошибки ключа, если изменятся сами ключи.
Ответ №5:
Вероятно, есть более краткий способ сделать это, и он зависит от структуры, которая в точности соответствует тому, что указано в вопросе, но она работает. Он отличается от ответа, данного ранее, тем, что позволяет использовать несколько ключей «тайны» в любом словаре OnDemand. Конечно, в этом может и не быть необходимости.
D = {'OnDemand': {
"QA3NBPZEQKZ2K9AR.JRTCKXETXF": {
"effectiveDate": "2021-08-01T00:00:00Z",
"offerTermCode": "JRTCKXETXF",
"priceDimensions": {
"QA3NBPZEQKZ2K9AR.JRTCKXETXF.6YS6EN2CT7": {
"appliesTo": [],
"beginRange": "0",
"description": "$0.0208 per On Demand Linux t3.small Instance Hour",
"endRange": "Inf",
"pricePerUnit": {
"USD": "0.0208000000"
},
"rateCode": "QA3NBPZEQKZ2K9AR.JRTCKXETXF.6YS6EN2CT7",
"unit": "Hrs"
}
},
"sku": "QA3NBPZEQKZ2K9AR",
"termAttributes": {}
}
}
}
base = D['OnDemand']
for b in base.keys():
pd = base[b]['priceDimensions']
for d in pd.keys():
print(pd[d]['pricePerUnit']['USD'])
Ответ №6:
Вы можете использовать dict.values()
, чтобы игнорировать ключи:
v = lambda d: list(d.values())[0]
hourly_cost = v(v(v(price_list))['priceDimensions'])['pricePerUnit']['USD']