See the following code,
if 'COMPONENTS' in prod.keys() and len(prod['COMPONENTS'])>0 and len(prod['COMPONENTS'][0])>1 and len(prod['COMPONENTS'][0][1])>0 and len(prod['COMPONENTS'][0][1][0])>2:
names = prod['COMPONENTS'][0][1][0][2]
if type(names) == list and len(names)>0 and type(names[0]) == str:
#names is proper. Now fetch prices
if len(prod['COMPONENTS'][0])>3:
lnames = len(names)
prices = [prod['COMPONENTS'][0][3][i][2][1][0][1] for i in range(0, lanmes)]
See how I am using prod['COMPONENTS'][0][1][0][2] and prod['COMPONENTS'][0][3][i][2][1][0][1]. prod is a very deep nested list. I want to check if element exists in such index.
I dind't find any way. Currently I am using a long condition on if statement. See above how long they are. They are terrible.
So is there any way to check if prod can satisfy ['COMPONENTS'][0][3][i][2][1][0][1] indexes?
Simplest way is just to do it and catch the error:
try:
names = prod['COMPONENTS'][0][1][0][2]
except LookupError:
print "It failed"
# Do whatever you need to do in case of failure
LookupError will catch missing indices in a list or missing keys in a dictionary.
Needless to say, though, you've already found the real problem: you're using an unwieldy and awkward data structure. It might be possible to bypass the problem by storing your data in a different way.
Related
I'm trying to read a json from mulitple REST end points using json.load - the key I'm interested in however has a different case depending on which end point (some are 'name' others are 'Name'). I've tried the following to get around it:
for x in urls:
response_json = json.load(urllib.request.urlopen(x))
try:
projects.append(response_json['attributes']['Name'])
print(response_json['attributes']['Name'])
except:
projects.append(response_json['attributes']['name'])
print(response_json['attributes']['name'])
However I'm getting KeyErrors for both permutations of the 'name' key. The code works fine if I remove the TRY...EXCEPT and only specify one case but then I need to know what is it for each URL. Why would that be? is there a better approach?
You should only use try and catch for error handling.
Instead of using try and catch to split your code, you can use a simple if-else condition check. It'll allow you to check for more conditions.
Keep in mind that the below might not be the exact code since I don't have your JSON, however, this should guide you towards the solution here.
if 'Name' in response_json['attributes']:
print(response_json['attributes']['Name'])
elif 'name' in response_json['attributes']:
print(response_json['attributes']['name'])
else:
print(response_json['attributes'].keys())
I have a JSON file with n number of dictionaries as listed below in the snippet. I am trying to fetch the value against the key but it fails in my code when the value is defined as a list like in the below example for key affected_packages. I tried to check why my code fails, so it looks like it pulls no data out of it this fails. I just see two brackets [] as output instead of "thunderbird-0:78.9.1-1.el8_1","thunderbird-0:78.9.1-1.el8_2","thunderbird-0:78.9.1-1.el8_3","thunderbird-0:78.9.1-1.el7_9"
{"bugzilla_description":"CVE-2021-23992 Mozilla: A crafted OpenPGP key with an invalid user ID could be used to confuse the user","cvss_score":null,"cvss_scoring_vector":null,"CWE":"CWE-347","affected_packages":["thunderbird-0:78.9.1-1.el8_1","thunderbird-0:78.9.1-1.el8_2","thunderbird-0:78.9.1-1.el8_3","thunderbird-0:78.9.1-1.el7_9"],"resource_url":"https://access.redhat.com/hydra/rest/securitydata/cve/CVE-2021-23992.json","cvss3_scoring_vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:L","cvss3_score":"4.3"}
I am doing like below in my code as I need to prepare a worksheet. Sample snippet:
for i in range(offs):
ws.cell(row=r+1+i,column=2).value = v['current'][i]
if 'affected_packages' in list(tmp1.keys()):
ws.cell(row=r+1+index1,column=11).value = tmp1['affected_packages']
print("affected_packages done")
if 'advisories' in list(tmp1.keys()):
ws.cell(row=r+1+index2,column=13).value = tmp1['advisories']
print("advisories done")
Is there a way I can pull the value correctly for those defined as a list in the dictionary? I need a way so that it won't hamper my existing logic to pull value for normal key: value since while looking up into my JSON file.
So need something which can fulfil both whether my value in the dictionary is as a list or not as a list and I can get value against the keys in my json file.
As mentioned in the other answers, you can test the type of a variable using
if type(some_variable) == list:
# do what you need to do
You do mention that your code breaks, and I guess it's because inserting into a cell expects a String, not the list you pass in the line
ws.cell(row=r+1+index1,column=11).value = tmp1['affected_packages']
So how do we get a string out of a list of strings? It's pretty easy using the join method.
my_list = ["thunderbird-0:78.9.1-1.el8_1","thunderbird-0:78.9.1-1.el8_2","thunderbird-0:78.9.1-1.el8_3","thunderbird-0:78.9.1-1.el7_9"]
as_one_string = ", ".join(my_list)
print(as_one_string)
# Prints out 'thunderbird-0:78.9.1-1.el8_1, thunderbird-0:78.9.1-1.el8_2, thunderbird-0:78.9.1-1.el8_3, thunderbird-0:78.9.1-1.el7_9'
So combining the two ideas:
if 'affected_packages' in list(tmp1.keys()):
ws.cell(row=r+1+index1,column=11).value = tmp1['affected_packages'] if type(tmp1['affected_packages']) != list else ", ".join(tmp1['affected_packages'])
print("affected_packages done")
Quick feedback because I can't comment yet: Please always include an error message and/or the output you get when running your code when you ask a question
If I understand it correctly, you just need to determine if a value in dict is list. You can do that as below:
for i in d.items(): # gets key, value as a tuple.
if isinstance(i[1],list):
print('its a list, process it accordingly')
else:
print('Not a list')
Regarding your second problem, when you don't know if it is a list or something else, you can just check the type, maybe like this:
if type(tmp1['affected_packages']) == list:
# process the list
else:
# process other types
Since you don't know the data type, having this explicit type check seems necessary.
I have a list with a few records:
entries = ['Agenda', 'Measure 1', 'Measure 2']
I am trying to create a loop and have them added to a table as listed below:
for i in range(0, len(entries)):
table.cell(i, 0).text = entries[i]
The below throws an IndexError: list index out of range on the last line, wondering where am I going wrong.
First things first, when iterating over range(len(something)) this is a red flag. There must be a better way.
If you need both the index as well as the value, you can use the built-in enumerate() function: for i, val in enumerate(entries):
The error you get means you're trying to access an element i that does not exist. The list elements should be accessible just fine - it's probably that table.cell(i,0) does not exist. You can verify this by trying:
for i in range(0, len(entries)):
print(entries[i]) # works
Compared to:
for i in range(0, len(entries)):
print(table.cell(i, 0).text) # probably doesn't work
I used your old for loop to show that's not causing the error, but know that range(len()) is a bad practice: it makes the code harder to read.
I'm not sure what kind of data structure you're using for table, but look up the related documentation and see how you should add new cells.
This is my first post, please be gentle. I'm attempting to sort some
files into ascending and descending order. Once I have sorted a file, I am storing it in a list which is assigned to a variable. The user is then to choose a file and search for an item. I get an error message....
TypeError: unorderable types; int() < list()
.....when ever I try to search for an item using the variable of my sorted list, the error occurs on line 27 of my code. From research, I know that an int and list cannot be compared, but I cant for the life of me think how else to search a large (600) list for an item.
At the moment I'm just playing around with binary search to get used to it.
Any suggestions would be appreciated.
year = []
with open("Year_1.txt") as file:
for line in file:
line = line.strip()
year.append(line)
def selectionSort(alist):
for fillslot in range(len(alist)-1,0,-1):
positionOfMax=0
for location in range(1,fillslot+1):
if alist[location]>alist[positionOfMax]:
positionOfMax = location
temp = alist[fillslot]
alist[fillslot] = alist[positionOfMax]
alist[positionOfMax] = temp
def binarySearch(alist, item):
first = 0
last = len(alist)-1
found = False
while first<=last and not found:
midpoint = (first + last)//2
if alist[midpoint] == item:
found = True
else:
if item < alist[midpoint]:
last = midpoint-1
else:
first = midpoint+1
return found
selectionSort(year)
testlist = []
testlist.append(year)
print(binarySearch(testlist, 2014))
Year_1.txt file consists of 600 items, all years in the format of 2016.
They are listed in descending order and start at 2017, down to 2013. Hope that makes sense.
Is there some reason you're not using the Python: bisect module?
Something like:
import bisect
sorted_year = list()
for each in year:
bisect.insort(sorted_year, each)
... is sufficient to create the sorted list. Then you can search it using functions such as those in the documentation.
(Actually you could just use year.sort() to sort the list in-place ... bisect.insort() might be marginally more efficient for building the list from the input stream in lieu of your call to year.append() ... but my point about using the `bisect module remains).
Also note that 600 items is trivial for modern computing platforms. Even 6,000 won't take but a few milliseconds. On my laptop sorting 600,000 random integers takes about 180ms and similar sized strings still takes under 200ms.
So you're probably not gaining anything by sorting this list in this application at that data scale.
On the other hand Python also includes a number of modules in its standard libraries for managing structured data and data files. For example you could use Python: SQLite3.
Using this you'd use standard SQL DDL (data definition language) to describe your data structure and schema, SQL DML (data manipulation language: INSERT, UPDATE, and DELETE statements) to manage the contents of the data and SQL queries to fetch data from it. Your data can be returned sorted on any column and any mixture of ascending and descending on any number of columns with the standard SQL ORDER BY clauses and you can add indexes to your schema to ensure that the data is stored in a manner to enable efficient querying and traversal (table scans) in any order on any key(s) you choose.
Because Python includes SQLite in its standard libraries, and because SQLite provides SQL client/server semantics over simple local files ... there's almost no downside to using it for structured data. It's not like you have to install and maintain additional software, servers, handle network connections to a remote database server nor any of that.
I'm going to walk through some steps before getting to the answer.
You need to post a [mcve]. Instead of telling us to read from "Year1.txt", which we don't have, you need to put the list itself in the code. Do you NEED 600 entries to get the error in your code? No. This is sufficient:
year = ["2001", "2002", "2003"]
If you really need 600 entries, then provide them. Either post the actual data, or
year = [str(x) for x in range(2017-600, 2017)]
The code you post needs to be Cut, Paste, Boom - reproduces the error on my computer just like that.
selectionSort is completely irrelevant to the question, so delete it from the question entirely. In fact, since you say the input was already sorted, I'm not sure what selectionSort is actually supposed to do in your code, either. :)
Next you say testlist = [].append(year). USE YOUR DEBUGGER before you ask here. Simply looking at the value in your variable would have made a problem obvious.
How to append list to second list (concatenate lists)
Fixing that means you now have a list of things to search. Before you were searching a list to see if 2014 matched the one thing in there, which was a complete list of all the years.
Now we get into binarySearch. If you look at the variables, you see you are comparing the integer 2014 with some string, maybe "1716", and the answer to that is useless, if it even lets you do that (I have python 2.7 so I am not sure exactly what you get there). But the point is you can't find the integer 2014 in a list of strings, so it will always return False.
If you don't have a debugger, then you can place strategic print statements like
print ("debug info: binarySearch comparing ", item, alist[midpoint])
Now here, what VBB said in comments worked for me, after I fixed the other problems. If you are searching for something that isn't even in the list, and expecting True, that's wrong. Searching for "2014" returns True, if you provide the correct list to search. Alternatively, you could force it to string and then search for it. You could force all the years to int during the input phase. But the int 2014 is not the same as the string "2014".
I need to check if the ID of a similar result exists in the exact results already and then exclude that result, I'm just unsure of the best way to do so.
I assume I'd have to find a way to iterate through both lists, then try something like if similar.ID != exact.ID and pass that to a variable to pass to the Jinja2 template.
The queries are being done with SQL-Alchemy like so;
exact_assets = Motor.query.filter_by(**filter_data).all()
similar_assets = Motor.query.filter_by(**similar_filter_data).all()
# Something like
# for similar_asset, exact_asset in similar_assets, exact_assets:
# if similiar_asset.id == asset.id:
# similar_asset.pop(id)
I know that syntax isn't correct, or even functional with a list or dict (?) but hopefully it is able to express what I'm trying to achieve here.
First create an list of keys to compare with (assuming that equality means same id from your code)
exact_assets_ids = [item.id for item in exact_assets]
Then filter your similar assets
final_assets = [item for item in similar_assets if item.id in exact_assets_ids]
Update: Just noticed that it is the intersection set :)
final_set = list(set(similar_assets) or set(exact_assets))
But in this case you should implement Motor.__eq__