Try keys in a dictionary until one works - python 2.7 - python

My dictionary contains keys (which may or may not repeat) and values (which are all unique). I get an exception error when my key, value pair does not work. When I get an exception, I would like to move to the next matching key, and try it's value. If none of them work, reach "finally" exception handler and just continue to next key.
Below is sort of the logic laid out, except my current logic would only try one other key possibility when I would like to exhaust all key options before reaching "finally".
for currentFile, originalFile in filepath_dictionary.items():
try:
relocateSource(currentFile, originalFile)
except:
# (Some logic which tries the next key, value pair in which the key matches the current key
finally:
print 'Could not relocate file: ' + currentFile

If you think that your keys repeat, but your values don't, then you have your data structure wrong, because dictionary keys are unique.
There are two possible solutions:
Reverse your dictionary structure so that the unique filenames are keys and the repeating filenames are the values.
Make each value of your dictionary a list of filenames, so that the several unique filenames are associated with the repeating filename. In other words, you represent the repetition of the repeating filename by associating it with several unique filenames instead of only one.
Taking the second option gives you something like this:
for current_file, original_files in filepath_dictionary.items():
for original_file in original_files:
try:
relocate_source(current_file, original_file)
break
except:
pass
else:
print 'Could not relocate file: ', current_file

In a Python dictionary, all keys are unique.

Maybe you should keep values of repeated keys in a list and simply search in that list if exception raises.
dct = {key1: [val2_k1, val2_k1], key2: [val2_k2]}

Related

Python KeyError with Windows filepath as key

I am trying to get the value from a dictionary with a filepath as the key and a number as the value. I am trying to get the value using the dict[key] method and when I configure the variable as either single backslash or double backslash I still get a KeyError when the variables look the same:
from pathlib import Path
print(job_slurm_dict)
print(Path(f'{site_dir}/hfoutp.in'))
try:
print(job_slurm_dict[Path(f'{site_dir}/hfoutp.in')])
except KeyError:
print('KEYERROR 1')
try:
print('\\\\'.join(f'{site_dir}\hfoutp.in'.split('\\')))
print(job_slurm_dict['\\\\'.join(f'{site_dir}\hfoutp.in'.split('\\'))])
except KeyError:
print('KEYERROR 2')
sys.exit(1)
I get the following output:
{'7ded3d66-8ed6-4edc-9127-b6ba2a598369\\reagent\\hfoutp.in': '17312073_1', '7ded3d66-8ed6-4edc-9127-b6ba2a598369\\3\\hfoutp.in': '17312073_2', '7ded3d66-8ed6-4edc-9127-b6ba2a598369\\4\\hfoutp.in': '17312073_3', '7ded3d66-8ed6-4edc-9127-b6ba2a598369\\6\\hfoutp.in': '17312073_4'}
7ded3d66-8ed6-4edc-9127-b6ba2a598369\3\hfoutp.in
KEYERROR 1
7ded3d66-8ed6-4edc-9127-b6ba2a598369\\3\\hfoutp.in
KEYERROR 2
When I try to print each key from the dictionary it looks like this: 7ded3d66-8ed6-4edc-9127-b6ba2a598369\3\hfoutp.in.
I am not sure why I am getting a KeyError when using this variable in either form to access the value from the dictionary since both the key and the variable are exactly the same.
Many thanks in advance.
The problem is that you are trying to print and access the dictionary with different data types.
In the first instance you are accessing the dictionary using a Path and in the second instance using a string. The reason it looks like the same key is because dictionary and Path converts differently to string. A string in a dictionary prints with double \\, while if you print the string directly it will just be one \.
If you convert the Path to string first, i.e., str(Path(...)), then it should work.

Web scraping table with missing attributes via Python Selenium and Pandas

Scraping a table from a website. But encountering empty cells during the process. Below try-except block is screwing up the data at the end. Also dont want to exclude the complete row, as the information is still relevant even when the some attribute is missing.
try:
for i in range(10):
data = {'ID': IDs[i].get_attribute('textContent'),
'holder': holder[i].get_attribute('textContent'),
'view': view[i].get_attribute('textContent'),
'material': material[i].get_attribute('textContent'),
'Addons': addOns[i].get_attribute('textContent'),
'link': link[i].get_attribute('href')}
list.append(data)
except:
print('Error')
Any ideas?
What you can do is place all the objects to which you want to access the attributes to in a dictionary like this:
objects={"IDs":IDs,"holder":holder,"view":view,"material":material...]
Then you can iterate through this dictionary and if the specific attribute does not exist, simply append an empty string to the value corresponding to the dict key. Something like this:
the_keys=list(objects.keys())
for i in range(len(objects["IDs"])): #I assume the ID field will never be empty
#so making a for loop like this is better since you iterate only through
#existing objects
data={}
for j in range(len(objects)):
try:
data[the_keys[j]]=objects[the_keys[j]][i].get_attribute('textContent')
except Exception as e:
print("Exception: {}".format(e))
data[the_keys[j]]="" #this means we had an exception
#it is better to catch the specific exception that is thrown
#when the attribute of the element does not exist but I don't know what it is
list.append(data)
I don't know if this code works since I didn't try it but it should give you an overall idea on how to solve your problem.
If you have any questions, doubts, or concerns please ask away.
Edit: To get another object's attribute like the href you can simply include an if statement checking the value of the key. I also realized you can just loop through the objects dictionary getting the keys and values instead of accessing each key and value by an index. You could change the inner loop to be like this:
for key,value in objects.items():
try:
if key=="link":
data[key]=objects[key][i].get_attribute("href")
else:
data[key]=objects[key][i].get_attribute("textContent")
except Exception as e:
print("Error: ",e)
data[key]=""
Edit 2:
data={}
for i in list(objects.keys()):
data[i]=[]
for key,value in objects.items():
for i in range(len(objects["IDs"])):
try:
if key=="link":
data[key].append(objects[key][i].get_attribute("href"))
else:
data[key].append(objects[key][i].get_attribute("textContent"))
except Exception as e:
print("Error: ",e)
data[key].append("")
Try with this. You won't have to append the data dictionary to the list. Without the original data I won't be able to help much more. I believe this should work.

Unable to store non-characters text in a dictionary in python

I am trying sentiment analysis where I have data like
source_text-> #LiesbethHBC I have a good feeling actually 🙈 its not that long, it's pretty soon!\nAw you deserve these tickets
then! 💖
result_value-> Sentiment(polarity=0.0, subjectivity=0.0)
I want to store this key value pair in a python dictionary.
I tried creating one as:
dict={}
dict[source_text].append(result_value)
but I get KeyError
Is there a way to store such text(just not characters) in a dictionary?
Your problem has nothing to do with "non-character text" (which doesn't mean anything actually), the only requirement for an object to be usable as a dict key is that it's hashable, and there's absolutely no restriction on what you can use as value.
Your problem quite simply comes from the fact that you're trying to get the value for an inexistant key (that's what KeyError means : the key you ask for does not exist in the dict).
Here :
mydict = {}
at this point, mydict is empty so just any item access will raise a KeyError
then you're doing this:
dict[source_text].append(result_value)
which is basically:
something = mydict[source_text] # get value for key `source_text`
something.append(result_value)
Since your dict is empty, the first line WILL obviously raise a KeyError.
If you want to store one unique result_value for each source_text value then the proper syntax is:
mydict[source_text] = result_value
If you want to store a list of result_value for each source_text value then you have to either explicitely test if the key is set, if not set it with an empty list, then append to this list:
if source_text not in mydict:
mydict[source_text] = []
mydict[source_text].append(result_value)
or just use a DefaultDict instead:
from collections import DefaultDict
mydict = DefaultDict(list)
# DefaultDict will automagically create the key with an empty list
# as value if the key is missing
mydict[source_text].append(result_value)
Now I strongly suggest that you invest some time in properly learning Python (hint: there's a quite decent tutorial in the official documentation) if you have to use it, this will save on everyone's time.
The problem is that when you tried to pull out the key #LiesbethHBC I have a good feeling actually 🙈 its not that long, it's pretty soon!\nAw you deserve these tickets then! 💖 in the dictionary which in this case is non-existent, Python gave you a KeyError meaning that the key didn't exist in the dictionary. A simple way to solve this is by initially checking whether you have that particular key in the dictionary, if yes, do whatever you wanna do with it, else create that key first.
By the way, avoid using dict (dictionary datatype) or any other datatypes as a variable name.
This is what you should actually do:
dictionary = {} # Since, 'dict' is the dictionary data-type in Python
if (source_text in dictionary):
# If the key exists...
dictionary[source_text].append(result_value)
else:
# If the key does not exist...
dictionary[source_text] = []
This should help...
Have you tried using '.update' method?
dict = {}
dict.update({'First':'Test'})
dict.update({'Lets Get':'Real'})
print (dict)
Output:
{'Testing': 'Dictionaries', 'Lets Get': 'Real'}
EDIT:
Or even:
dict = {}
dict.update({'Polarity':0.91})
dict.update({'Subjectivity':0.73})
print (dict)
Output:
{'Polarity': 0.8, 'Subjectivity': 0.73}

Check if a string appears in any of the keys of a dictionary

I'm trying to check if a string is in one of the keys of a dictionary.
if message in a_dict: # this will only work if message is exactly one of the keys
#do stuff
I want the condition to return True even if message is only part of one of a_dict's keys.
How would I do that? Is there a way to add a regex .* in the string? Or is there a better way?
You can use any:
elif any(message in key for key in a_dict):
do_something()
If you need also the key which contains the message:
else:
key = next((message in key for key in a_dict), None)
if key is not None:
do_something(key)
You can't really do what you want with Python's in operator. It's best to do the check by hand - iterate over all the keys and see if any of them contains your message.

Matching a string with a dictionary value exactly and retrieving the key - python

I have a dictionary which i fetch from MySql DB, the ID is the key and the value is a string (relative Windows path of files to be exact). I have another list which has windows path as elements. Now, I need to match the list elements with the dictionary values and if exact match is found, i need to retrieve the key for that element, if not present, i'll update in the DB
My current code:
for line in f1:
line = line.strip()
try:
index = next(k for (k,v) in self.db_file_list.iteritems() if line in v)
file_list_csv.append(index)
The problem here is: Suppose value in my dictionary is "abc def", "a/b/c"
then if i search values "abc" or "a/b" it would still match and give me key value which is not what i want.
Please help me out, i am a newbie to Python.
Many thanks in advance!
~Saurav
If your only problem is that you would be matching substring matches as well, then replacing line in v with line == v would be enough (take care to use == in this case and not is: is does an identity comparison, whereas == simply compares values).

Categories

Resources