Error: too many values to unpack (expected 2) - python

I am having the aforementioned error in my python code. I am working on a google colab.
def create_dataset(path, num_examples):
lines = io.open(path, encoding='UTF-8').read().strip().split('\n')
#print(lines)
word_pairs = [[preprocess_sentence(w) for w in l.split('\t')] for l in lines[:num_examples]]
print(path)
return zip(*word_pairs)
sample_size=60000
source, target = create_dataset(data_path, sample_size)
print(source[-1])
print(target[-1])
type(target)
Following error appears while I try to compile the code:
1 sample_size=60000
----> 2 source, target = create_dataset(data_path, sample_size)
3 print(source[-1])
4 print(target[-1])
5 type(target)
ValueError: too many values to unpack (expected 2)
Guidance will be highly appreciated.

You are returning a zip object which is an iterator of tuples. Your tuple size is > 2 and so you are getting that error on source, target = create_dataset(data_path, sample_size).
Simple example of same is below:
>>> a = [['a', 'b', 'c'], [1, 2, 3]]
>>> x,y = zip(*a)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: too many values to unpack (expected 2)
>>> tuple(zip(*a))
(('a', 1), ('b', 2), ('c', 3))
>>>

Related

Python: Too Many values to unpack on return

I hope, this is not a duplicate. I know what too many values to unpack means. I am returning two values, and trying to accept two values.
I am providing only a short part of the code, I hope it will be enough.
def test(all the arguments in function_parameters):
// do something
dfData.append([fileToCheck,5,";".join(faceNames),frameTime,";".join(faceDistances),";".join(faceLocations),";".join(gender),str(";".join(age)),str(";".join(expression))])
if len(face_locations) != 0:
keyPointsData.append([fileToCheck,time,str(";".join(encodings)),str(";".join(encodings)),time])
else:
keyPointsData.append([fileToCheck,time,"","",time])
return dfData, keyPointsData
#Start multiprocessing
#Pass variables to the function
function_parameters = zip(
images_to_check,
itertools.repeat(known_names),
itertools.repeat(known_face_encodings),
itertools.repeat(tolerance),
itertools.repeat(processImages),
itertools.repeat(processVideos),
itertools.repeat(fpstoprocess),
itertools.repeat(upsample),
itertools.repeat(algo),
itertools.repeat(onlydetection),
itertools.repeat(saveimagespath),
itertools.repeat(savefullimages),
itertools.repeat(savefaceimage),
itertools.repeat(enablebox),
itertools.repeat(maxarea),
listNumber,
itertools.repeat(totalImages),
itertools.repeat(imageExtensions),
itertools.repeat(videoExtensions),
itertools.repeat(debug),
itertools.repeat(age),
itertools.repeat(gender),
itertools.repeat(expression),
itertools.repeat(keypointsDF)
)
rows,keypointsData = pool.starmap(test, function_parameters)
tdfData and keyPointsData are multidimensional list. I am using Multi threads
I am getting error at this line rows,keypointsData = pool.starmap(test, function_parameters)
Full Error Message
Traceback (most recent call last):
File "face.py", line 829, in <module>
main()
File "face.py", line 702, in main
process_images_in_process_pool()
File "face.py", line 584, in process_images_in_process_pool
rows,keypointsData = pool.starmap(test, function_parameters)
ValueError: too many values to unpack (expected 2)
As per the official docs https://docs.python.org/3/library/multiprocessing.html#multiprocessing.pool.Pool.starmap
starmap takes an iterator to call the function with different input from iterator and then return another iterator with all the output with their corresponding inputs.
So here take an example:
def test(a, b):
return a, b
now calling the function with iterator of different input:
iter1 = zip([1, 2], [3, 4])
list_of_results = pool.starmap(test, iter1)
>>> list_of_results
>>> [(2, 3), (4, 5)]
x, y = pool.starmap(test, iter1) # unpacking will work
But in case of iterator call more times than 2 unpacking with 2 variables will fail:
iter2 = zip([1, 2, 3], [4, 5, 6])
list_of_results = pool.starmap(test, iter2)
>>> list_of_results
>>> [(2, 5), (3, 6), (4, 7)]
x, y = pool.starmap(test, iter1) # unpacking will fail
Therefore first store the result in list_of_results and then iterate over it to use the output values to avoid unpacking issue.
Hope it will clear the doubt and issue

python generator conversion

i would like to know how to convert a generator with only one element into list.For example if f is a generator with one element,list(f) will raise "not iterable".how to solve this problem ?thanks in advance!
nx.adamic_adar_index(g, (0, 1))
list(nx.adamic_adar_index(g, (0, 1)))
this will raise TypeError: 'int' object is not iterable,the following is OK
nx.adamic_adar_index(g, [(0, 1),(2,3)])
list(nx.adamic_adar_index(g, [(0, 1),(2,3)]))
the result is [(0, 1, 2.3878841007006875), (2, 3, 0.9282626109897467)]
If I understand correctly, this: [(0, 1),(2,3)] is a list of two elements (each being a tuple of two elements) but (0, 1) is a single element, could it be that you need to be a list of a single element, like [(0, 1)]?
I'd guess that:
list(nx.adamic_adar_index(g, [(0, 1)]))
will do what you want.
Could this be it?
The generator must be evaluated to be listed. You can't list the generator itself.
>>> def g():
... yield 1
...
>>> list(g())
[1]
>>> list(g)
Traceback (most recent call last):
File "<interactive input>", line 1, in <module>
TypeError: 'function' object is not iterable

Index Python fetchall()

I'm trying to figure out how to use Python with MySQL. I'm having trouble addressing entries in the query results.
So if I do something like this:
import MySQLdb
db = MySQLdb.connect(host="192.168.178.10",
user="user",
passwd="password",
db="testdb")
cur = db.cursor()
cur.execute("select * from Persons;")
print(cur.fetchall()[2][2])
db.close()
I get the third entry of the third row which seems plausible.
If I do this:
print(cur.fetchall()[0][0:2])
I get the first to entries of the first row. Which also seems plausible.
However if I do something like this:
print(cur.fetchall()[0:2][2])
I get the error:
Traceback (most recent call last):
File "mysql.py", line 19, in <module>
print(cur.fetchall()[0:2][2])
IndexError: tuple index out of range
Which I do not understand.
Also I am unable to get (for example) all the first entries of all the rows. To achieve this it seems I need to do a loop through the entries I want.
Could someone clarify what I'm doing wrong or how this works?
Greetings!
First of all, without a specified ordering you do not get "third row" with
cur.execute("select * from Persons;")
print(cur.fetchall()[2][2])
You get a random row. It may seem stable enough, but do not trust it.
The reason you get IndexError: tuple index out of range is that with
print(cur.fetchall()[0:2][2])
you take a slice of elements from 0 to 1 from the result set and then you try to take the 3rd element with [2], which does not exist, since your slice had 2 elements.
E.g.
In [1]: rows = tuple(zip(range(10), range(10)))
In [2]: rows
Out[2]:
((0, 0),
(1, 1),
(2, 2),
(3, 3),
(4, 4),
(5, 5),
(6, 6),
(7, 7),
(8, 8),
(9, 9))
In [3]: rows[0:2]
Out[3]: ((0, 0), (1, 1))
In [4]: rows[0:2][0]
Out[4]: (0, 0)
In [5]: rows[0:2][2]
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-5-2b13f1394ba3> in <module>()
----> 1 rows[0:2][2]
IndexError: tuple index out of range
To actually take the 3rd attribute from the result tuples you can use for example a map or a list comprehension:
In [6]: rows = tuple(zip(range(10), range(10), range(10,20)))
In [7]: [r[2] for r in rows[0:2]]
Out[7]: [10, 11]
A tuple of list elements when queried with range of indexes returns another set of tuple with list of elements.
>>> t = ([1,2,3],[4,5,6],[7,8,9],)
>>> print( t[0:2] ) # 2 is number of lists in the resulting tuple
([1, 2, 3], [4, 5, 6])
Here you can observe that resulting tuple size is 2 elements. And indexes can be 0 and 1 only. Hence following statement fails.
>>> print( t[0:2][2] ) # [2] is pointing to non existing index
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: tuple index out of range
>>>
Correct statement can be this.
>>> print( t[0:2][1] )
[4, 5, 6]
If I understand correct, your intention is to find 2nd column value from first 2 rows from the dataset fetched. Possible statement can be:
>>> for x in t[0:2]: print (x)
...
[1, 2, 3]
[4, 5, 6]
>>>
>>> for x in t[0:2]: print (x[2])
...
3
6
>>>
Hence, the statement
print(cur.fetchall()[0:2][2])
can be re-written as:
rows = cur.fetchall()[ 0:2 ]
for row in rows: print ( row[ 2 ] )

Cant understand some python tuple syntax

I started learning python today and found this very nice code visualization tool pythontutor.com, the problem is that I still don't quite get some of the syntax on the example code.
def listSum(numbers):
if not numbers:
return 0
else:
(f, rest) = numbers
return f + listSum(rest)
myList = (1, (2, (3, None)))
total = listSum(myList)
What does (f, rest) = numbers means?
It's tuple unpacking.
There needs to be 2 items in the tuple when used in this way. More or less will result in an exception, as shown below.
>>> numbers = (1, 2, 3, 4, 5)
>>> (f, rest) = numbers
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: too many values to unpack
>>> numbers = (1, 2)
>>> (f, rest) = numbers
>>> print f
1
>>> print rest
2
>>> numbers = (1)
>>> (f, rest) = numbers
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'int' object is not iterable
>>> numbers = (1,)
>>> (f, rest) = numbers
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: need more than 1 value to unpack
Note that (1) and (1, )are syntactically different, with only the latter being a tuple.
See the Python Doc on Tuples and Sequences for more details.
(f, rest) = numbers
unpacks the tuple. That is, it takes the two values stored in numbers and stores them in f and rest, respectively. Note that the number of variables you unpack into must be the same as the number of values in the tuple, or else an exception will be thrown.
Tupple is a data structure in which you can store multiple items under one name.
Lets say that we have a tupple(t) with two items.
Then t[0] = first_item and t[1] = sencond_item
Another way of accessing the tupple item is:
(f, rest) = numbers
In this syntax numbers (tupple) must have 2 items only otherwise it is an exception
f = numbers[0]
rest = numbers[1]

how to cast multiple integers as a ctypes array of c_ubyte in Python

How does one convert a string of colon-separated hexadecimal numbers into a ctypes array of c_ubyte? According to the ctypes docs, I can cast a hard-coded collection, like so:
>>> from ctypes import *
>>> x = (c_ubyte * 6) (1, 2, 3, 4, 5, 6)
>>> x
<__main__.c_ubyte_Array_6 object at 0x480c5348>
Or, like so:
>>> XObj = c_ubyte * 6
>>> x = XObj(1, 2, 3, 4, 5, 6)
>>> x
<__main__.c_ubyte_Array_6 object at 0x480c53a0>
However, I cannot figure how to cast a variable list, like one generated from splitting a string, for example:
>>> mac = 'aa:bb:cc:dd:ee:ff'
>>> j = tuple(int(z,16) for z in mac.split(':'))
>>> j
(170, 187, 204, 221, 238, 255)
>>> x = (c_ubyte * 6) (j)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: an integer is required
>>> XObj = c_ubyte * 6
>>> x = XObj(j)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: an integer is required
What am I missing?
Thanks!
The problem is that in the first example you provided, you've used ctypes correctly by giving 6 arguments to XObj call, and in the second example (with mac address), you try to call the same object c_ubyte * 6, giving it a tuple, but not 6 values, so convert it using *args notation:
from c_types import c_ubyte
mac = 'aa:bb:cc:dd:ee:ff'
j = tuple(int(z,16) for z in mac.split(':'))
converted = (c_ubyte * 6)(*j) # *j here is the most signigicant part
print converted
And the result is:
<__main__.c_ubyte_Array_6 object at 0x018BD300>
as expected.

Categories

Resources