ValueError output when upacking tuple

Hi,

I just started learning Python and while I was playing with Tuples I noticed that the ValueError output differs if you provide less than the exact number of elements in the tuple. For example:

>>> tuple = (1, 2, 3)
>>> (a, b) = tuple
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: too many values to unpack (expected 2)


>>> (a, b, c, d) = tuple
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: not enough values to unpack (expected 4, got 3)

My question is:

Why in case of too many values to unpack error, the output doesn’t show how many elements in the tuple are there?

I peeked into CPython code on GitHub but I don’t understand code well enough yet.

Thanks!

It doesn’t have to be a tuple on the right hand side. It can also be a iterator:

def foo():
    for i in range(1_000_000):
        yield i

it = foo()
x, y = it

After x and y got assigned a value, it would still not completely exhausted but at that point it is clear that it has more than 2 elements. No need to continue iterating until 1_000_000.

It is also clear if you check the next value in it:

next(it)
Out: 3
3 Likes

Welcome to Python…

You didn’t mention which version of Python you’re using (noting version and platform are always a good idea when asking a question), but I suspect it might be a bit older than current GitHub source. If you scroll down to line 2238, notice that the current code does indicate the size of the time to be unpacked. I just checked, and see that 3.13 behaves as you saw, while the yet-to-be-released 3.14 includes the tuple size in its error message. (This only applies to dicts, lists and tuples, no even subclasses of them.) That code was updated 2024-09-10.

2 Likes

Oh, such a cool feature! In the case of unpacking the iterator, it is impossible to know how many elements it will return before executing it and getting to the end - as far as I understand… Thanks for sharing this!

Oh, I forgot to mention the version. You’re right, it is older than the GitHub source, I was using Python 3.10.11 on intel macbook.

If you scroll down to line 2238, notice that the current code does indicate the size of the time to be unpacked.

I saw line 2234, where the size isn’t indicated, so I thought this was what I was getting in the output - but I guess this output is only in case of other data types other than lists, dicts and tuples.

I also just checked the code for the version I was using it doesn’t have that additional if:

Thank you for help!

I thought about mentioning that, but didn’t. I imagine it would be pretty easy to fabricate an unpackable object whose length can’t be determined.

1 Like
>>> from __future__ import patience
>>> import itertools
>>> (a, b) = itertools.count()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: too many values to unpack (expected 2)
(still counting...)
(wait for it...)
(wait for it...)
(wait for it...)
(wait for it...)