ValueError: too many values to unpack - python

I am trying to sort dictionaries in MongoDB. However, I get the value error "too many values to unpack" because I think it's implying that there are too many values in each dictionary (there are 16 values in each one). This is my code:
FortyMinute.find().sort(['Rank', 1])
Anyone know how to get around this?
EDIT: Full traceback
Traceback (most recent call last):
File "main.py", line 33, in <module>
main(sys.argv[1:])
File "main.py", line 21, in main
fm.readFortyMinute(args[0])
File "/Users/Yih-Jen/Documents/Rowing Project/FortyMinute.py", line 71, in readFortyMinute
writeFortyMinute(FortyMinData)
File "/Users/Yih-Jen/Documents/Rowing Project/FortyMinute.py", line 104, in writeFortyMinute
FortyMinute.find().sort(['Rank', 1])
File "/Users/Yih-Jen/anaconda/lib/python2.7/site-packages/pymongo/cursor.py", line 692, in sort
self.__ordering = helpers._index_document(keys)
File "/Users/Yih-Jen/anaconda/lib/python2.7/site-packages/pymongo/helpers.py", line 65, in _index_document
for (key, value) in index_list:
ValueError: too many values to unpack

You pass the arguments and values in unpacked as so:
FortyMinute.find().sort('Rank', 1)
It is only when you're passing multiple sort parameters that you group arguments and values using lists, and then too you must surround all your parameters with a tuple as so:
FortyMinute.find().sort([(Rank', 1), ('Date', 1)])
Pro-tip: Even the Cursor.sort documentation linked below recommends using pymongo.DESCENDING and pymongo.ASCENDING instead of 1 and -1; in general, you should use descriptive variable names instead of magic constants in your code as so:
FortyMinute.find().sort('Rank',pymongo.DESCENDING)
Finally, if you are so inclined, you can sort the list using Python's built-in as the another answerer mentioned; but even thought sorted accepts iterators and not just sequences it might be more inefficient and nonstandard:
sorted(FortyMinute.find(), key=key_function)
where you might define key_function to return the Rank column of a record.
Link to the official documentation

If you want mong/pymongo to sort:
FortyMinute.find().sort('Rank', 1)
If you want to sort using multiple fields:
FortyMinute.find().sort([('Rank': 1,), ('other', -1,)])
You also have constants to make it more clear what you're doing:
FortyMinute.find().sort('Rank',pymongo.DESCENDING)
If you want to sort in python first you have to return the result and use a sorting method in python:
sorted(FortyMinute.find(), key=<some key...>)

Related

accessing nested dictionaries when you know the nested key?

This one is probably pretty easy, but I can't figure it out! Suppose I have a dictionary with a nested dictionary, that I know the nested dictionary key that I can store in a variable, how would I access this value?
k = 'mynested'
nestedk = 'blah'
x = {}
x['mynested'] = {}
x['mynested']['blah'] = 1
print(x[k[nestedk]])
throws error:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: string indices must be integers
There is a slight mistake in your last line print(x[k[nestedk]]). This line actually means that you are treating the k variable as a list which is actually a string and the characters of the string can only be accessed by an integer index and not by a string index.
Change the last line to the below
print(x[k][nestedk])
You can get it with x[k][nestedk]. You can access the values similar to assigning values inside dictionary. As you are assigning
X[k] = {}
and x[k][nestedk] = 1
The value is 1 and key for nested object is k so initially we get the inner dictionary by x[k] and then we get the value using nested key in your case nestedk.
Thus you have to correct your print statement like below
print(x[k][nestedk])

populating word template with python .merge() but TypeError: merge() argument after ** must be a mapping, not str

I am trying to create a script that will take in user info and populate word templates with the information.
I keep getting the following error and I don't understand why:
TypeError: merge() argument after ** must be a mapping, not str
My script begins by gathering information from the user and storing it into a dictionary. then the following code is executed:
stress_notes_document = MailMerge(os.path.join(new_path,new_notes))
stress_notes_document.merge(
TR_num = packet_info['TR#'],
pckg_num = packet_info['Package#'],
TED_num = packet_info['TED#'],
Charge_Line = packet_info['Charge Line'],
Change_num = packet_info['Change#'],
Installation_list = packet_list['Installations list'],
Drawings_list = packet_list['Drawings list'],
Designer = packet_info['Designer'],
phone_number_designer = packet_info['Phone Number of designer'],
Date_in = packet_info['Date in'],
Stress_Due_Date = packet_info['Stress Due Date'],
Date_out = packet_info['Date out'],
model = packet_info['model'],
Customer = packet_info['Customer'],
Effectivity = packet_info['Effectivity'],
panel_excel = 'new_panel')
stress_notes_document.write(os.path.join(new_path,new_notes + "ver A"))
The error happens when I try to execute the second line, stress_notes_document.merge(..). I am trying to assign a value from my dictionary to a mergefield in the word document.
Any suggestions?
edit: I am using this as a guide: http://pbpython.com/python-word-template.html
The examples shown they use strings in the merge() function.
Here is the full error :
Traceback (most recent call last):
File "<ipython-input-1-e67354559525>", line 1, in <module>
runfile('C:/Python_All/python_scripts/data_gather.py', wdir='C:/Python_All/python_scripts')
File "C:\Python_All\Anaconda\lib\site-packages\spyder\utils\site\sitecustomize.py", line 710, in runfile
execfile(filename, namespace)
File "C:\Python_All\Anaconda\lib\site-packages\spyder\utils\site\sitecustomize.py", line 101, in execfile
exec(compile(f.read(), filename, 'exec'), namespace)
File "C:/Python_All/python_scripts/data_gather.py", line 114, in <module>
Effectivity = packet_info['Effectivity'])
File "C:\Python_All\Anaconda\lib\site-packages\mailmerge.py", line 176, in merge
self.merge_rows(field, replacement)
File "C:\Python_All\Anaconda\lib\site-packages\mailmerge.py", line 219, in merge_rows
self.merge([row], **row_data)
TypeError: merge() argument after ** must be a mapping, not str
The reason for the error is that one of parameter values you pass to merge() is a list not a string.
merge() as described in the docs enables you to pass list of dictionaries as a shortcut to merge_rows() function. So if you pass code as below (taken from docs) then it runs merge_rows() function using given list.
document.merge(field1='docx Mail Merge',
col1=[
{'col1': 'A'},
{'col1': 'B'},
])
Now, in your code one of the values you provide (packet_list['Installations list'] from comments) is a list, so merge() decides to run merge_rows on that. But format of your list does not match the expected format (expected format is list with dictionaries as elements, but in your code elements are strings). Thus you get error, when merge_rows tries to read provided data as dictionary.
To fix this you either convert list packet_list['Installations list'] into a string, for example:
",".join(packet_list['Installations list'] )
or convert that list into expected list of dictionaries format.
Whichever makes sense.

Pandas DataFrame exists in list

I tried searching but didnt see anything relevant, or it may have skipped my eyes.
So what I want is pretty specific. I have a list of Pandas DataFrame, and I want to check wheather the dataframe created in current step / workflow already exists in list, if yes then pass or else append to it. Now I tried using following:
if df not in best_dfs:
# process something here
best_dfs.append(df)
else:
pass
This is how you would do to check weather a list contains some object of fixed type. But When I do the same, I recieve following error:
Traceback (most recent call last):
File "C:/Projects/Barclays/Email Analytics/POC - Stop Cheque Classification/03_CodeBase/CodeBase/utils/FindBestDf.py", line 239, in <module>
print(obj.find_(dfs))
File "C:/Projects/Barclays/Email Analytics/POC - Stop Cheque Classification/03_CodeBase/CodeBase/utils/FindBestDf.py", line 19, in find_
r = self.__driver(list_of_df)
File "C:/Projects/Barclays/Email Analytics/POC - Stop Cheque Classification/03_CodeBase/CodeBase/utils/FindBestDf.py", line 201, in __driver
if v[0] not in best_dfs:
File "C:\Users\IBM_ADMIN\Anaconda3\lib\site-packages\pandas\core\ops.py", line 1296, in f
return self._compare_frame(other, func, str_rep)
File "C:\Users\IBM_ADMIN\Anaconda3\lib\site-packages\pandas\core\frame.py", line 3670, in _compare_frame
raise ValueError('Can only compare identically-labeled '
ValueError: Can only compare identically-labeled DataFrame objects
How do I tacke this? Any work around?
Any help will be grately appreciated.
Thanks
Probably not the most efficient way, but this works for pandas:
if not True in [df.equals(x) for x in df_list]:
df_list.append(df)
Pandas has a built-in method to check for df equality called df.equals(). Basically you iterate this through your df_list to create another list of result, then check if any of the result return True (i.e. the same df exist in the list).

converting tuple to dictionary in python

I am trying to convert a line of string to dictionary where i am facing an error.
here is what i have and what i did:
line="nsd-1:quorum"
t=tuple(line.split(":"))
d=dict(t)
Traceback (most recent call last):
File "<pyshell#2>", line 1, in <module>
d=dict(t)
ValueError: dictionary update sequence element #0 has length 5; 2 is required
Basically, what i want to achieve is to have a key value pair.
So if i have set of values separated by a ":", i want to have it as a key whatever is before the colon and after the colon needs to be the value for the key.
example: if i take the above string, i want "nsd-1" as my key and "quorum" as value.
Any help is appreciated.
Thanks
Wrap it in a list:
>>> dict([t])
{'nsd-1': 'quorum'}
There's also no need to convert the return value of split to a tuple:
>>> dict([line.split(':')])
{'nsd-1': 'quorum'}
Put t inside an empty list, like this:
d=dict([t])

How do I unpack a list with fewer variables?

k = [u'query_urls', u'"kick"', u'"00"', u'msg=1212', u'id=11']
>>> name, view, id, tokens = k
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: too many values to unpack
I need to provide 5 variables to unpack this list. Is there a way to unpack with fewer, so that tokens gets the rest of the list. I don't want to write another line to append to a list....
Thanks.
Of course I can slice a list, assign individually, etc. But I want to know how to do what I want using the syntax above.
In Python 3 you can do this: (edit: this is called extended iterable unpacking)
name, view, id, *tokens = k
In Python 2, you will have to do this:
(name, view, id), tokens = k[:3], k[3:]

Categories

Resources