I have a dictionary that holds different value and id's.
The first index in the dictionary does not hold the 'id' dictionary, but the second index does
The problem I am having is when I print:
return[0]['values']['id']
It returns
'id'
Because there is no such dictionary in the first index
The second index
return[1]['values']['id']
The 'id' dictionary does exist so returns
[{"id": "4651234", "type":"instant"}]
I'm trying to create a list of only the id values that exist, how do I get it to skip the all the indexes where the 'id' dictionary does not exist? Rather than stop the program and print the string 'id'.
You can just loop and use a if statement to check if the id exists or not :
id_list = []
for key in return:
if return[key]['values']['id'] != 'id':
id_list.append(return[key]['values']['id'])
(Btw you should avoid naming your variables with name like return or any other keyword that can have a signification for the language)
you can if the returned value it is a list or a string
if isinstance(return[0]['values']['id'],list):
#process the data
elif isinstance(return[0]['values']['id'],str):
#do nothing
Having said that, a couple of recommendations: I assume that you wrote it as an example but, just in case, is not possible to have "return" as the name of the variable since it is a reserved word.
Another point is that if the same call returns different things (i.e. the first returns a str, the second a list with a dictionary in it, etc), it may be an indication that the data needs some cleaning before trying to access it. Otherwise you may end up with nasty results and you won't know where they are coming from.
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 am looking to assess if there is a better method to append to a list within a list within a dictionary.
I have many different packets and associated strings to search for in a huge text file. Associated to each string is a value I want to store in a list so that I can perform calculations like average/max/min.
Due to the packet variations and associated strings for each packet I was looking to keep a dictionary entry to a single line. So I would have a Key as the packet ID and the value as a list of elements, see below
mycompactdict={
"packetID_001":[12,15,'ID MATCH',[['search_string',[] ],['search_string2',[] ]]]
"packetID_002":[...etc]
}
The 12,15 ints are references I use later in Excel plotting. The 'ID_MATCH' entry is my first check to see if the packet ID matches the file object. The 'search_string' references are the strings I am looking for and the blank lists next to them is where I hope to drop the values associated to each search string after splitting the line in the text file.
Now I may be biting off more than Python can chew... I realize there is a list within a list within a list within a list within a dict!
Here's a start of my code...
def process_data(file_object):
split_data = file_object.split('\n')
for key in mycompactdict:
if mycompactdict[key][2] in file_object:
for line in split_data:
if item[0] for item in mycompactdict[key][3] in line:
value = line.split('=', 1)
value.strip()
print value
and then append the stripped value to mycompactdict[key][6]item[1]
Am I on the wrong approach which will cause performance problems later on, and is there a cleaner alternative?
Below is an example of the file_object in the for of a unicode block of text, there are both matching and differing packet IDs I need to account for.
14:27:42.0 ID_21 <<(ID_MATCH)
Type = 4
Fr = 2
search_string1 = -12
search_string2 = 1242
I would not try to re-invent the wheel were I in your position. Thus, I would use Pandas. It has something called DataFrames that would be a good fit for what you are trying to do. In addition, you can export those into exel spread sheets. Have a look at the 10min introduction.
I am newbie in python and mod_wsgi development. When I want to get data from POST i read envron['wsgi.input'] and as a result I get name=username&fullname=name&pass=password. Now my question is how to split it to get that input as array. For example to read like name = arraypost[0]?
You could split the data and pass it into dict() to create a dictionary of key, value pairs:
post_dict = dict([item.split('=') for item in envron['wsgi.input'].split('&')])
print post_dict['name']
print post_dict['fullname']
print post_dict['pass']
Here I'm demonstrating how to do it in Python 3. Using urllib.parse.parse_qs converts it to a dictionary of lists.
import urllib.parse
post = urllib.parse.parse_qs(environ['QUERY_STRING'])
# get value of first instance of POST var 'foo'
print(post.get(b'foo',[''])[0])
Note the use of get() above. The first argument is a byte string, the second argument is a default value. As I said, it's a dictionary of lists, and since we're immediately fetching from index 0, we want at least a zero-length string there so we don't go out-of-bounds.
To start I am a complete new comer to Python and programming anything other than web languages.
So, I have developed a script using Python as an interface between a piece of Software called Spendmap and an online app called Freeagent. This script works perfectly. It imports and parses the text file and pushes it through the API to the web app.
What I am struggling with is Spendmap exports multiple lines per order where as Freeagent wants One line per order. So I need to add the cost values from any orders spread across multiple lines and then 'flatten' the lines into One so it can be sent through the API. The 'key' field is the 'PO' field. So if the script sees any matching PO numbers, I want it to flatten them as per above.
This is a 'dummy' example of the text file produced by Spendmap:
5090071648,2013-06-05,2013-09-05,P000001,1133997,223.010,20,2013-09-10,104,xxxxxx,AP
COMMENT,002091
301067,2013-09-06,2013-09-11,P000002,1133919,42.000,20,2013-10-31,103,xxxxxx,AP
COMMENT,002143
301067,2013-09-06,2013-09-11,P000002,1133919,359.400,20,2013-10-31,103,xxxxxx,AP
COMMENT,002143
301067,2013-09-06,2013-09-11,P000003,1133910,23.690,20,2013-10-31,103,xxxxxx,AP
COMMENT,002143
The above has been formatted for easier reading and normally is just one line after the next with no text formatting.
The 'key' or PO field is the first bold item and the second bold/italic item is the cost to be totalled. So if this example was to be passed through the script id expect the first row to be left alone, the Second and Third row costs to be added as they're both from the same PO number and the Fourth line to left alone.
Expected result:
5090071648,2013-06-05,2013-09-05,P000001,1133997,223.010,20,2013-09-10,104,xxxxxx,AP
COMMENT,002091
301067,2013-09-06,2013-09-11,P000002,1133919,401.400,20,2013-10-31,103,xxxxxx,AP
COMMENT,002143
301067,2013-09-06,2013-09-11,P000003,1133910,23.690,20,2013-10-31,103,xxxxxx,AP
COMMENT,002143
Any help with this would be greatly appreciated and if you need any further details just say.
Thanks in advance for looking!
I won't give you the solution. But you should:
Write and test a regular expression that breaks the line down into its parts, or use the CSV library.
Parse the numbers out so they're decimal numbers rather than strings
Collect the lines up by ID. Perhaps you could use a dict that maps IDs to lists of orders?
When all the input is finished, iterate over that dict and add up all orders stored in that list.
Make a string format function that outputs the line in the expected format.
Maybe feed the output back into the input to test that you get the same result. Second time round there should be no changes, if I understood the problem.
Good luck!
I would use a dictionary to compile the lines, using get(key,0.0) to sum values if they exist already, or start with zero if not:
InputData = """5090071648,2013-06-05,2013-09-05,P000001,1133997,223.010,20,2013-09-10,104,xxxxxx,AP COMMENT,002091
301067,2013-09-06,2013-09-11,P000002,1133919,42.000,20,2013-10-31,103,xxxxxx,AP COMMENT,002143
301067,2013-09-06,2013-09-11,P000002,1133919,359.400,20,2013-10-31,103,xxxxxx,AP COMMENT,002143
301067,2013-09-06,2013-09-11,P000003,1133910,23.690,20,2013-10-31,103,xxxxxx,AP COMMENT,002143"""
OutD = {}
ValueD = {}
for Line in InputData.split('\n'):
# commas in comments won't matter because we are joining after anyway
Fields = Line.split(',')
PO = Fields[3]
Value = float(Fields[5])
# set up the output string with a placeholder for .format()
OutD[PO] = ",".join(Fields[:5] + ["{0:.3f}"] + Fields[6:])
# add the value to the old value or to zero if it is not found
ValueD[PO] = ValueD.get(PO,0.0) + Value
# the output is unsorted by default, but you could sort or preserve original order
for POKey in ValueD:
print OutD[POKey].format(ValueD[POKey])
P.S. Yes, I know Capitals are for Classes, but this makes it easier to tell what variables I have defined...