I have been working with BOTO 3 to describe all load balancers available in the account. I used the following snippet of code:
'elbv2=boto3.client('elbv2',aws_access_key_id=access_key_id,aws_secret_access_key=secret_key,region_name=region)
response=elbv2.describe_load_balancers()
print(response)
The response here stores the dict with all the information, like so:
{
'LoadBalancers': [{
'LoadBalancerArn': 'arn:aws:elasticloadbalancing:ap-south-1:407203256002:loadbalancer/net/aws-lb-02/9d4b15bfd6f579d3',
'DNSName': 'aws-lb-02-9d4b15bfd6f579d3.elb.ap-south-1.amazonaws.com',
'CanonicalHostedZoneId': 'ZVDDRBQ08TROA',
'CreatedTime': datetime.datetime(2021, 3, 31, 11, 45, 6, 729000, tzinfo = tzutc()),
'LoadBalancerName': 'aws-lb-02',
'Scheme': 'internet-facing',
'VpcId': 'vpc-0be01860',
'State': {
'Code': 'active'
},
'Type': 'network',
'AvailabilityZones': [{
'ZoneName': 'ap-south-1a',
'SubnetId': 'subnet-ed5fb986',
'LoadBalancerAddresses': []
}, {
'ZoneName': 'ap-south-1b',
'SubnetId': 'subnet-89d285c5',
'LoadBalancerAddresses': []
}]]}"'
I want to access LoadBalancerAddress , which I tried like this:
LoadBalancers=response['LoadBalancers']
for i in LoadBalancers:
AvailabilityZones=i['AvailabilityZones']
for j in AvailabilityZones:
LoadBalancerAddresses=i['LoadBalancerAddresses']
However, it throws an error saying that there is a keyword error for LoadBalancerAddresses, which I fail to understand.
Please help in how should I access the variable.
you can use nested list comprehension here, like that:
addresses = [x['LoadBalancerAddresses'] for res in aaa['LoadBalancers'] for x in res['AvailabilityZones']]
or with ordinar nested lists:
addresses = []
for bal in aaa['LoadBalancers']:
for zones in bal['AvailabilityZones']:
addresses += zones['LoadBalancerAddresses']
You mistyped j['LoadBalancerAddresses'] as i['LoadBalancerAddresses']. Since there are no keys named LoadBalancerAddresses directly under response['LoadBalancers'], your program throws a KeyError.
The fixed version:
LoadBalancers=response['LoadBalancers']
for i in LoadBalancers:
AvailabilityZones=i['AvailabilityZones']
for j in AvailabilityZones:
LoadBalancerAddresses=j['LoadBalancerAddresses']
As a safety option, it's good practice to check if the key exists before you access it, such as:
for j in AvailabilityZones:
if "LoadBalancerAddresses" in j:
LoadBalancerAddresses=j['LoadBalancerAddresses']
else:
print("The key does not exist")
Related
I'm managing an api and I would like to understand why I have the error "AttributeError 'bytes' object has no attribute 'get'"
import requests
from requests.auth import HTTPBasicAuth
incidents = []
limit = 100
offset = 0
got_all_events = False
while not got_all_events:
alerts = requests.get(f'***', auth=HTTPBasicAuth('***', '***'))
print(alerts)
for alert in alerts:
incident = {
'name': alert.get('hostname'),
'rawJSON': json.dumps(alert),
}
incidents.append(incident)
if len(alerts) == limit:
offset += limit
else:
got_all_events = True
print(incident)
The error is regarding this code line
'name': alert.get('hostname'),
From my api my array is defined like that:
{
"totalSize": 0,
"data": [
{
"hostname": "string",
"domain": "string",
"tags": "string",
"os": {},
}
],
"size": 0
}
Your dictionary has the hostname key nested in a subdictionary as part of a list, so the get is unable to find it.
The only valid targets for the get on alert are totalsize, data, and size.
You could run a get on alert with key data to return a list, then run another get on position 0 of that list with key hostname to get what you want.
A more straightforward approach would just be:
'name': alert["data"][0]["hostname"]
alerts is a requests.Response object, not something decoded from JSON. You have to extract the body first. The iterator for a Response yields a sequence of bytes values, which is where the bytes value you think should be a dict comes from.
response = requests.get(f'***', auth=HTTPBasicAuth('***', '***'))
alerts = response.json()
for alert in alerts:
incident = {
'name': alert.get('hostname'),
'rawJSON': json.dumps(alert),
}
incidents.append(incident)
Thanks for your help.
Now it is working like that:
r=alerts.json()
for alert in r['data']:
incident = {
'hostName': alert["hostname"],
}
incidents.append(incident)
print(json.dumps(incidents, indent=1))
I'm using boto3 to verify if a cloudformation stack already exists. The code for this is:
import boto3
import botocore
conn = boto3.client('cloudformation')
list_stack = conn.list_stacks()['StackSummaries']
for stack in list_stack:
if stack['StackStatus'] == 'DELETE_COMPLETE':
continue
if stack['StackName'] == stack_name:
return True
return False
The conn.list_stack() returns a dict.
This code works properly.
What I don't understand is why I need to put ['StackSummaries'] after the list_stack()? I've never seen this kind of code where you put the key of a dictionary after the function. I just don get it the syntax.
And if I don use this way a get this error message:
TypeError: string indices must be integers
So I need to use with the suntax that I don understand. Can someone explain how this works?
The output for list_stacks() is:
{
'StackSummaries': [
{
'StackId': 'string',
'StackName': 'string',
'TemplateDescription': 'string',
'CreationTime': datetime(2015, 1, 1),
'LastUpdatedTime': datetime(2015, 1, 1),
'DeletionTime': datetime(2015, 1, 1),
'StackStatus': 'CREATE_IN_PROGRESS'|'CREATE_FAILED'|'CREATE_COMPLETE'|'ROLLBACK_IN_PROGRESS'|'ROLLBACK_FAILED'|'ROLLBACK_COMPLETE'|'DELETE_IN_PROGRESS'|'DELETE_FAILED'|'DELETE_COMPLETE'|'UPDATE_IN_PROGRESS'|'UPDATE_COMPLETE_CLEANUP_IN_PROGRESS'|'UPDATE_COMPLETE'|'UPDATE_ROLLBACK_IN_PROGRESS'|'UPDATE_ROLLBACK_FAILED'|'UPDATE_ROLLBACK_COMPLETE_CLEANUP_IN_PROGRESS'|'UPDATE_ROLLBACK_COMPLETE'|'REVIEW_IN_PROGRESS'|'IMPORT_IN_PROGRESS'|'IMPORT_COMPLETE'|'IMPORT_ROLLBACK_IN_PROGRESS'|'IMPORT_ROLLBACK_FAILED'|'IMPORT_ROLLBACK_COMPLETE',
'StackStatusReason': 'string',
'ParentId': 'string',
'RootId': 'string',
'DriftInformation': {
'StackDriftStatus': 'DRIFTED'|'IN_SYNC'|'UNKNOWN'|'NOT_CHECKED',
'LastCheckTimestamp': datetime(2015, 1, 1)
}
},
],
'NextToken': 'string'
}
The outer-most dictionary element is StackSummaries, which contains a list.
So, it is returning the list.
Instead of:
list_stack = conn.list_stacks()['StackSummaries']
for stack in list_stack:
they could have used:
stacks = conn.list_stacks()
for stack in stacks['StackSummaries']:
The good thing is that they called it list_stacks, which suggests that the contents is a list.
I need to store the value of 'Address' in a variable for later use. The 'address' value is deep inside an output from a json.dump.
From what I've gathered over looking through some similar issues is that I need to iterate between each value in order access the ScriptPubKey (dict). Since I am only a few hours in to Python, without much prior knowledge about programming, I'm sure that I'm missing something simple - or completely misunderstand the task at hand.
for x in response['result']['vout']:
for y in x:
print(y)
So this is the part of the program I am having issues with:
###Function
def gettranshash(transhashen):
payload = {
"method": "getrawtransaction",
"params": [transhashen],
}
response = requests.post(url, data=json.dumps(payload), headers=headers).json()
response = response['result']
payload = {
"method": "decoderawtransaction",
"params": [response],
}
response = requests.post(url, data=json.dumps(payload), headers=headers).json()
return response
###How I access the function in my program
transaktionshash = input("write transactionhash for a block: ")
response = gettranshash(transaktionshash)
print("Blocket: ", response['result']['hash'])
###Missing the address output :(
print("Blocket: ", response['result']['vout'])
Result from response:
{'result': {'txid':
'4d879b24d65dd418a8e806ed69df7f170022e89666590a7b08e0095009865a5b',
'hash':
'4d879b24d65dd418a8e806ed69df7f170022e89666590a7b08e0095009865a5b',
'version': 1, 'size': 87, 'vsize': 87, 'locktime': 0, 'vin':
[{'coinbase': '0163', 'sequence': 4294967295}], 'vout': [{'value': 50.0,
'n': 0, 'scriptPubKey': {'asm': 'OP_DUP OP_HASH160
071e31b8289aa9d80b970230cb1b8b76466f2ec4 OP_EQUALVERIFY OP_CHECKSIG',
'hex': '76a914071e31b8289aa9d80b970230cb1b8b76466f2ec488ac', 'reqSigs':
1, 'type': 'pubkeyhash', 'addresses':
['1eduGsrvBJcfyTMij2rYXk9viiVV78PNq']}}]}, 'error': None, 'id': None}
This is the result from response['result']['vout']:
[{'value': 50.0, 'n': 0, 'scriptPubKey': {'asm': 'OP_DUP OP_HASH160
071e31b8289aa9d80b970230cb1b8b76466f2ec4 OP_EQUALVERIFY OP_CHECKSIG',
'hex': '76a914071e31b8289aa9d80b970230cb1b8b76466f2ec488ac', 'reqSigs':
1,
'type': 'pubkeyhash', 'addresses':
['1eduGsrvBJcfyTMij2rYXk9viiVV78PNq']}}]
this is from the documentation:
"vout" : [ (array of json objects)
{
"value" : x.xxx, (numeric) The value in BTC
"n" : n, (numeric) index
"scriptPubKey" : { (json object)
"asm" : "asm", (string) the asm
"hex" : "hex", (string) the hex
"reqSigs" : n, (numeric) The required sigs
"type" : "pubkeyhash", (string) The type, eg
'pubkeyhash'
"addresses" : [ (json array of string)
"address" (string) bitcoin address
,...
]
}
}
,...
],
So basically; I need to access the 'address' value in order to use it as input in an iteration for a different function.
Many thanks for any potential tips and let me know if I need to add additional information or clarify anything:)
In a python script,
I'm trying for elasticsearch.helpers.bulk to store multiple records.
I will get a json-format string from another software, and I want to attach it in the source part
I got the helpers.bulk format by this answer
part of my code:
def saveES(output,name):
es = Elasticsearch([{'host':'localhost','port':9200}])
output = output.split('\n')
i=0
datas=[]
while i<len(output):
data = {
"_index":"name",
"_type":"typed",
"_id":saveES.counter,
"_source":[[PROBLEM]]
}
i+=1
saveES.counter+=1
datas.append(data)
helpers.bulk(es, datas)
I would like to attach a json-format string in [[PROBLEM]]
How can I attach it in? I have tried hard, but it is not output in the correct..
if I use:
"_source":{
"image_name":'"'+name+'",'+output[i]
}
and print data result is:
{'_type': 'typed', '_id': 0, '_source': {'image_name': '"nginx","features": "os,disk,package", "emit_shortname": "f0b03efe94ec", "timestamp": "2017-08-18T17:25:46+0900", "docker_image_tag": "latest"'}, '_index': 'name'}
This result show that combined into a single string.
but I expect:
{'_type': 'typed', '_id': 0, '_source': {'image_name': 'nginx','features': 'os,disk,package', 'emit_shortname': 'f0b03efe94ec', 'timestamp': '2017-08-18T17:25:46+0900', 'docker_image_tag': 'latest'}, '_index': 'name'}
There is many problems in your code.
You override the value of data in your loop
You don't respect any norms (Pesp8 and stuff)
You are while instead of a comprehension list
You created 2 useless variable
You instantiate your es in your function
Here is your improved code
es = Elasticsearch([{'host':'localhost','port':9200}]) # You don't have to initialise this variable every time you are calling the function but only once.
def save_es(output,es): # Peps8 convention
output = output.split('\n') # you don't need a while loop. A comprehension loop will avoid a lot of trouble
data = [ # Please without s in data
{
"_index": "name",
"_type": "typed",
"_id": index,
"_source": {
"image_name":"name" + name}
}
for index, name in enumerate(output)
]
helpers.bulk(es, data)
save_es(output, es)
Hope this help.
I have written code to migrate data from sql server 2008 to PostGreSQL using OpenERPLib in Python for OpenERP. I want to set the value of "categ_id" column of type "Many2one" of "crm.opportunity2phonecall" object. Here below is my existing code.
scheduleCall = {
'name': 'test',
'action': ['schedule'],
'phone': "123456",
'user_id': 1,
"categ_id": 10,
'note': mail['body']
}
SCHEDULECALL_MODEL.create(scheduleCall)
SCHEDULECALL_MODEL = OECONN.get_model("crm.opportunity2phonecall")
In the above code i have set the hard-coded value "10" for "categ_id" field as per my requirement. When i execute above code, it gives me an error -
TypeError: unhashable type: 'list'
Try assigning a list instead of an integer as follows:
categ_id: [10]
anyway, as Atul said in his comment, update OpenERP with xmlrpc, it is safe and stable, and suppports different versions of OpenERP
Okay, I got the solution.
What i had done is - define one method in python which returns categ_id and set its value in "scheduleCall" dict and surprisingly its work. Here is my code.
scheduleCall = {
'name': 'test',
'action': ['schedule'],
'phone': "123456",
'user_id': 1,
"categ_id": get_categid_by_name('Outbound'),
'note': mail['body']
}
SCHEDULECALL_MODEL.create(scheduleCall)
SCHEDULECALL_MODEL = OECONN.get_model("crm.opportunity2phonecall")
And here is the method that i had define.
def get_categid_by_name(name):
"""return category id"""
categ_id = False
ids = CATEG_MODEL.search([('name', '=', name)])
categ_id = ids[0]
return categ_id
CATEG_MODEL = OECONN.get_model("crm.case.categ")
Hope it'll help to others.