Cookie Policy

We use cookies to operate this website, improve usability, personalize your experience, and improve our marketing. Privacy Policy.

By clicking "Accept" or further use of this website, you agree to allow cookies.

Accept
Learn Machine Learning by Doing Learn Now
You are reading solutions / Python
alfie-grace-headshot-square2.jpg
Author: Alfie Grace
Data Scientist

ValueError: too many values to unpack (expected 2)

ValueError: too many values to unpack

Why does this occur?

Unpacking refers to retrieving values from a list and assigning them to a list of variables. This error occurs when the number of variables doesn't match the number of values. As a result of the inequality, Python doesn't know which values to assign to which variables, causing us to get the error ValueError: too many values to unpack.

Today, we'll look at some of the most common causes for this ValueError. We'll also consider the solutions to these problems, looking at how we can avoid any issues.

Cause 1: List Unpacking

One of the most frequent causes of this error occurs when unpacking lists.

Let's say you've got a list of kitchen appliances, where you'd like to assign the list values to a couple of variables. We can emulate this process below:

appliances = ['Fridge', 'Microwave', 'Toaster']
appliance_1, appliance_2 = appliances
Out:
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-4-2c62c443595d> in <module>
      1 appliances = ['Fridge', 'Microwave', 'Toaster']
----> 2 appliance_1, appliance_2 = appliances

ValueError: too many values to unpack (expected 2)

We're getting this traceback because we're only assigning the list to two variables when there are three values in the list.

As a result of this, Python doesn't know if we want Fridge, Microwave or Toaster. We can quickly fix this:

Solution

appliances = ['Fridge', 'Microwave', 'Toaster']
appliance_1, appliance_2, appliance_3 = appliances

With the addition of applicance_3, this snippet of code runs successfully since we now have an equal amount of variables and list values.

This change communicates to Python to assign Fridge, Microwave, and Toaster to appliance_1, appliance_2, and appliance_3, respectively.

Cause 2: Unpacking Function Returns

Let's say we want to write a function that performs computations on two variables, variable_1 and variable_2, then return the results for use elsewhere in our program.

Specifically, here's a function that gives us the sum, product and quotient of two variables:

def compute(x, y): 
    sum = x + y
    product = x * y
    quotient = x / y
    return sum, product, quotient

result_1, result_2 = compute(12, 5)
Out:
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-5-9e571b686b4f> in <module>
      6     return sum, product, quotient
      7 
----> 8 result_1, result_2 = compute(12, 5)

ValueError: too many values to unpack (expected 2)

This error is occurs because the function returns three variables, but we are only asking for two.

Python doesn't know which two variables we're looking for, so instead of assuming and giving us just two values (which could break our program later if they're the wrong values), the value error alerts us that we've made a mistake.

There are a few options that you can use to capture the function's output successfully. Some of the most common are shown below.

Solution

First we'll define the function once more:

def compute(x, y): 
    sum = x + y
    product = x * y
    quotient = x / y
    return sum, product, quotient

Option 1: Assign return values to three variables.

result_1, result_2, result_3 = compute(12, 5)

print(f"Option 1: sum={result_1}, product={result_2}, quotient={result_3}")
Out:
Option 1: sum=17, product=60, quotient=2.4

Now that Python can link the return of sum, product, and quotient directly to result_1, result_2, and result_3, respectively, the program can run without error.

Option 2: Use an underscore to throw away a return value.

result_1, result_2, _ = compute(12, 5)

print(f"Option 2: sum={result_1}, product={result_2}")
Out:
Option 2: sum=17, product=60

The standalone underscore is a special character in Python that allows you to throw away return values you don't want or need. In this case, we don't care about the quotient return value, so we throw it away with an underscore.

Option 3: Assign return values to one variable, which then acts like a tuple.

results = compute(12, 5)

print(f"Option 3: sum={results[0]}, product={results[1]}, quotient={results[2]}")
Out:
Option 3: sum=17, product=60, quotient=2.4

With this option, we store all return values in results, which can then be indexed to retrieve each result. If you end up adding more return values later, nothing will break as long as you don't change the order of the return values.

Cause 3: Dealing with Inconsistencies

This ValueError can also occur when reading files. Let's say we have records of student test results in a text file, and we want to read the data to conduct further analysis. The file test_results.txt looks like this:

80,76,84 83,81,71 89,67,,92 73,80,83

Using the following script, we could create a list for each student, which stores all of their test results after iterating through the lines in the txt file:

with open('test_results.txt', 'r') as f:
    file_content = f.read()

file_lines = file_content.split('\n') # split file into a list of lines

student_1_scores, student_2_scores, student_3_scores = [], [], []

for line in file_lines:
    student_1_score, student_2_score, student_3_score = line.split(',')
    student_1_scores.append(student_1_score)
    student_2_scores.append(student_2_score)
    student_3_scores.append(student_3_score)
Out:
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-14-70781b12ee1c> in <module>
      7 
      8 for line in file_lines:
----> 9     student_1_score, student_2_score, student_3_score = line.split(',')
     10     student_1_scores.append(student_1_score)
     11     student_2_scores.append(student_2_score)
ValueError: too many values to unpack (expected 3)

If you look back at the text file, you'll notice that the third line has an extra comma. The line.split(',') code causes Python to create a list with four values instead of the three values Python expects.

One possible solution would be to edit the file and manually remove the extra comma, but this would be tedious to do with a large file containing thousands of rows of data.

Another possible solution could be to add functionality to your script which skips lines with too many commas, as shown below:

Solution

with open('test_results.txt', 'r') as f:
    file_content = f.read()

file_lines = file_content.split('\n')

student_1_scores, student_2_scores, student_3_scores = [], [], []

for index, line in enumerate(file_lines):
    try:
        student_1_score, student_2_score, student_3_score = line.split(',')
    except ValueError:
        print(f'ValueError row {index + 1}')
        continue
        
    student_1_scores.append(student_1_score)
    student_2_scores.append(student_2_score)
    student_3_scores.append(student_3_score)
Out:
ValueError row 3

We use try except to catch any ValueError and skip that row. Using continue, we can bypass the rest of the for loop functionality. We're also printing the problematic rows to alert the user, which allows them to fix the file. In this case, we get the message shown in the output for our code above, alerting the user that line 3 is causing an error.

Summary

We get this error when there's a mismatch between the number of variables to the amount of values Python receives from a function, list, or other collection.

The most straightforward way of avoiding this error is to consider how many values you need to unpack and then have the correct number of available variables. In situations where the number of values to unpack could vary, the best approaches are to capture the values in a single variable (which becomes a tuple) or including features in your program that can catch these situations and react to them appropriately.


Meet the Authors

alfie-grace-headshot-square2.jpg

Alfie graduated with a Master's degree in Mechanical Engineering from University College London. He's currently working as Data Scientist at Square Enix. Find him on LinkedIn.

Brendan Martin
Editor: Brendan
Founder of LearnDataSci

Get updates in your inbox

Join over 7,500 data science learners.